Search in sources :

Example 11 with DocumentWindow

use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.

the class CodeFormatterFacade method processText.

public void processText(PsiFile file, final FormatTextRanges ranges, boolean doPostponedFormatting) {
    final Project project = file.getProject();
    Document document = PsiDocumentManager.getInstance(project).getDocument(file);
    final List<FormatTextRange> textRanges = ranges.getRanges();
    if (document instanceof DocumentWindow) {
        file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file);
        final DocumentWindow documentWindow = (DocumentWindow) document;
        for (FormatTextRange range : textRanges) {
            range.setTextRange(documentWindow.injectedToHost(range.getTextRange()));
        }
        document = documentWindow.getDelegate();
    }
    final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
    final Language contextLanguage = file.getLanguage();
    if (builder != null) {
        if (file.getTextLength() > 0) {
            LOG.assertTrue(document != null);
            try {
                final FileViewProvider viewProvider = file.getViewProvider();
                final PsiElement startElement = viewProvider.findElementAt(textRanges.get(0).getTextRange().getStartOffset(), contextLanguage);
                final PsiElement endElement = viewProvider.findElementAt(textRanges.get(textRanges.size() - 1).getTextRange().getEndOffset() - 1, contextLanguage);
                final PsiElement commonParent = startElement != null && endElement != null ? PsiTreeUtil.findCommonParent(startElement, endElement) : null;
                ASTNode node = null;
                if (commonParent != null) {
                    node = commonParent.getNode();
                }
                if (node == null) {
                    node = file.getNode();
                }
                for (FormatTextRange range : ranges.getRanges()) {
                    TextRange rangeToUse = preprocess(node, range.getTextRange());
                    range.setTextRange(rangeToUse);
                }
                if (doPostponedFormatting) {
                    RangeMarker[] markers = new RangeMarker[textRanges.size()];
                    int i = 0;
                    for (FormatTextRange range : textRanges) {
                        TextRange textRange = range.getTextRange();
                        int start = textRange.getStartOffset();
                        int end = textRange.getEndOffset();
                        if (start >= 0 && end > start && end <= document.getTextLength()) {
                            markers[i] = document.createRangeMarker(textRange);
                            markers[i].setGreedyToLeft(true);
                            markers[i].setGreedyToRight(true);
                            i++;
                        }
                    }
                    final PostprocessReformattingAspect component = file.getProject().getComponent(PostprocessReformattingAspect.class);
                    FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
                    component.doPostponedFormatting(file.getViewProvider());
                    i = 0;
                    for (FormatTextRange range : textRanges) {
                        RangeMarker marker = markers[i];
                        if (marker != null) {
                            range.setTextRange(TextRange.create(marker));
                            marker.dispose();
                        }
                        i++;
                    }
                }
                if (FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get()) {
                    return;
                }
                final FormattingModel originalModel = CoreFormatterUtil.buildModel(builder, file, mySettings, FormattingMode.REFORMAT);
                final FormattingModel model = new DocumentBasedFormattingModel(originalModel, document, project, mySettings, file.getFileType(), file);
                FormatterEx formatter = FormatterEx.getInstanceEx();
                if (CodeStyleManager.getInstance(project).isSequentialProcessingAllowed()) {
                    formatter.setProgressTask(new FormattingProgressTask(project, file, document));
                }
                CommonCodeStyleSettings.IndentOptions indentOptions = mySettings.getIndentOptionsByFile(file, textRanges.size() == 1 ? textRanges.get(0).getTextRange() : null);
                formatter.format(model, mySettings, indentOptions, ranges, myReformatContext);
                for (FormatTextRange range : textRanges) {
                    TextRange textRange = range.getTextRange();
                    wrapLongLinesIfNecessary(file, document, textRange.getStartOffset(), textRange.getEndOffset());
                }
            } catch (IncorrectOperationException e) {
                LOG.error(e);
            }
        }
    }
}
Also used : DocumentBasedFormattingModel(com.intellij.psi.formatter.DocumentBasedFormattingModel) TextRange(com.intellij.openapi.util.TextRange) DocumentWindow(com.intellij.injected.editor.DocumentWindow) DocumentBasedFormattingModel(com.intellij.psi.formatter.DocumentBasedFormattingModel) Project(com.intellij.openapi.project.Project) PostprocessReformattingAspect(com.intellij.psi.impl.source.PostprocessReformattingAspect) Language(com.intellij.lang.Language) ASTNode(com.intellij.lang.ASTNode) CommonCodeStyleSettings(com.intellij.psi.codeStyle.CommonCodeStyleSettings) IncorrectOperationException(com.intellij.util.IncorrectOperationException)

Example 12 with DocumentWindow

use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.

the class CodeFormatterFacade method preprocess.

private TextRange preprocess(@NotNull final ASTNode node, @NotNull TextRange range) {
    TextRange result = range;
    PsiElement psi = node.getPsi();
    if (!psi.isValid()) {
        return result;
    }
    PsiFile file = psi.getContainingFile();
    // We use a set here because we encountered a situation when more than one PSI leaf points to the same injected fragment
    // (at least for sql injected into sql).
    final LinkedHashSet<TextRange> injectedFileRangesSet = ContainerUtilRt.newLinkedHashSet();
    if (!psi.getProject().isDefault()) {
        List<DocumentWindow> injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(file);
        if (!injectedDocuments.isEmpty()) {
            for (DocumentWindow injectedDocument : injectedDocuments) {
                injectedFileRangesSet.add(TextRange.from(injectedDocument.injectedToHost(0), injectedDocument.getTextLength()));
            }
        } else {
            Collection<PsiLanguageInjectionHost> injectionHosts = collectInjectionHosts(file, range);
            PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {

                @Override
                public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
                    for (PsiLanguageInjectionHost.Shred place : places) {
                        Segment rangeMarker = place.getHostRangeMarker();
                        injectedFileRangesSet.add(TextRange.create(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()));
                    }
                }
            };
            for (PsiLanguageInjectionHost host : injectionHosts) {
                InjectedLanguageUtil.enumerate(host, visitor);
            }
        }
    }
    if (!injectedFileRangesSet.isEmpty()) {
        List<TextRange> ranges = ContainerUtilRt.newArrayList(injectedFileRangesSet);
        Collections.reverse(ranges);
        for (TextRange injectedFileRange : ranges) {
            int startHostOffset = injectedFileRange.getStartOffset();
            int endHostOffset = injectedFileRange.getEndOffset();
            if (startHostOffset >= range.getStartOffset() && endHostOffset <= range.getEndOffset()) {
                PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(file, startHostOffset);
                if (injected != null) {
                    int startInjectedOffset = range.getStartOffset() > startHostOffset ? startHostOffset - range.getStartOffset() : 0;
                    int endInjectedOffset = injected.getTextLength();
                    if (range.getEndOffset() < endHostOffset) {
                        endInjectedOffset -= endHostOffset - range.getEndOffset();
                    }
                    final TextRange initialInjectedRange = TextRange.create(startInjectedOffset, endInjectedOffset);
                    TextRange injectedRange = initialInjectedRange;
                    for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
                        injectedRange = processor.process(injected.getNode(), injectedRange);
                    }
                    // Allow only range expansion (not reduction) for injected context.
                    if ((initialInjectedRange.getStartOffset() > injectedRange.getStartOffset() && initialInjectedRange.getStartOffset() > 0) || (initialInjectedRange.getEndOffset() < injectedRange.getEndOffset() && initialInjectedRange.getEndOffset() < injected.getTextLength())) {
                        range = TextRange.create(range.getStartOffset() + injectedRange.getStartOffset() - initialInjectedRange.getStartOffset(), range.getEndOffset() + initialInjectedRange.getEndOffset() - injectedRange.getEndOffset());
                    }
                }
            }
        }
    }
    if (!mySettings.FORMATTER_TAGS_ENABLED) {
        for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
            result = processor.process(node, result);
        }
    } else {
        result = preprocessEnabledRanges(node, result);
    }
    return result;
}
Also used : TextRange(com.intellij.openapi.util.TextRange) NotNull(org.jetbrains.annotations.NotNull) Segment(com.intellij.openapi.util.Segment) DocumentWindow(com.intellij.injected.editor.DocumentWindow) List(java.util.List)

Example 13 with DocumentWindow

use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.

the class MultiHostRegistrarImpl method freezeWindow.

@NotNull
public static DocumentWindow freezeWindow(@NotNull DocumentWindowImpl window) {
    Place shreds = window.getShreds();
    Project project = shreds.getHostPointer().getProject();
    DocumentEx delegate = ((PsiDocumentManagerBase) PsiDocumentManager.getInstance(project)).getLastCommittedDocument(window.getDelegate());
    Place place = new Place(ContainerUtil.map(shreds, shred -> ((ShredImpl) shred).withPsiRange()));
    return new DocumentWindowImpl(delegate, window.isOneLine(), place);
}
Also used : DocumentEx(com.intellij.openapi.editor.ex.DocumentEx) Language(com.intellij.lang.Language) com.intellij.openapi.util(com.intellij.openapi.util) VirtualFileWindow(com.intellij.injected.editor.VirtualFileWindow) PsiFileImpl(com.intellij.psi.impl.source.PsiFileImpl) TreeElement(com.intellij.psi.impl.source.tree.TreeElement) SmartPointerManagerImpl(com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl) IElementType(com.intellij.psi.tree.IElementType) VirtualFile(com.intellij.openapi.vfs.VirtualFile) NonNls(org.jetbrains.annotations.NonNls) ContainerUtil(com.intellij.util.containers.ContainerUtil) BlockSupportImpl(com.intellij.psi.impl.source.text.BlockSupportImpl) ArrayList(java.util.ArrayList) FileContextUtil(com.intellij.psi.impl.source.resolve.FileContextUtil) ProcessCanceledException(com.intellij.openapi.progress.ProcessCanceledException) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) SyntaxHighlighter(com.intellij.openapi.fileTypes.SyntaxHighlighter) SmartList(com.intellij.util.SmartList) Map(java.util.Map) Project(com.intellij.openapi.project.Project) DocumentEx(com.intellij.openapi.editor.ex.DocumentEx) SyntaxHighlighterFactory(com.intellij.openapi.fileTypes.SyntaxHighlighterFactory) DocumentImpl(com.intellij.openapi.editor.impl.DocumentImpl) MultiHostRegistrar(com.intellij.lang.injection.MultiHostRegistrar) LightVirtualFile(com.intellij.testFramework.LightVirtualFile) Lexer(com.intellij.lexer.Lexer) DebugUtil(com.intellij.psi.impl.DebugUtil) DiffLog(com.intellij.psi.impl.source.text.DiffLog) DocumentWindow(com.intellij.injected.editor.DocumentWindow) StringUtil(com.intellij.openapi.util.text.StringUtil) DocumentWindowImpl(com.intellij.injected.editor.DocumentWindowImpl) TreeUtil(com.intellij.psi.impl.source.tree.TreeUtil) FileElement(com.intellij.psi.impl.source.tree.FileElement) ReferenceInjector(com.intellij.psi.injection.ReferenceInjector) FileDocumentManagerImpl(com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl) ASTNode(com.intellij.lang.ASTNode) ParserDefinition(com.intellij.lang.ParserDefinition) DocumentCommitThread(com.intellij.psi.impl.DocumentCommitThread) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) PsiUtilCore(com.intellij.psi.util.PsiUtilCore) PsiDocumentManagerBase(com.intellij.psi.impl.PsiDocumentManagerBase) LeafElement(com.intellij.psi.impl.source.tree.LeafElement) DaemonProgressIndicator(com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator) LanguageParserDefinitions(com.intellij.lang.LanguageParserDefinitions) com.intellij.psi(com.intellij.psi) PathUtil(com.intellij.util.PathUtil) NotNull(org.jetbrains.annotations.NotNull) VirtualFileWindowImpl(com.intellij.injected.editor.VirtualFileWindowImpl) Project(com.intellij.openapi.project.Project) DocumentWindowImpl(com.intellij.injected.editor.DocumentWindowImpl) PsiDocumentManagerBase(com.intellij.psi.impl.PsiDocumentManagerBase) NotNull(org.jetbrains.annotations.NotNull)

Example 14 with DocumentWindow

use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.

the class MultiHostRegistrarImpl method registerDocument.

// under com.intellij.psi.PsiLock.LOCK
private static PsiFile registerDocument(final DocumentWindowImpl documentWindow, final PsiFile injectedPsi, final Place shreds, final PsiFile hostPsiFile, final PsiDocumentManager documentManager) {
    List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
    for (int i = injected.size() - 1; i >= 0; i--) {
        DocumentWindowImpl oldDocument = (DocumentWindowImpl) injected.get(i);
        final PsiFileImpl oldFile = (PsiFileImpl) documentManager.getCachedPsiFile(oldDocument);
        FileViewProvider viewProvider;
        if (oldFile == null || !oldFile.isValid() || !((viewProvider = oldFile.getViewProvider()) instanceof InjectedFileViewProvider) || ((InjectedFileViewProvider) viewProvider).isDisposed()) {
            injected.remove(i);
            Disposer.dispose(oldDocument);
            continue;
        }
        InjectedFileViewProvider oldViewProvider = (InjectedFileViewProvider) viewProvider;
        final ASTNode injectedNode = injectedPsi.getNode();
        final ASTNode oldFileNode = oldFile.getNode();
        assert injectedNode != null : "New node is null";
        if (oldDocument.areRangesEqual(documentWindow)) {
            if (oldFile.getFileType() != injectedPsi.getFileType() || oldFile.getLanguage() != injectedPsi.getLanguage()) {
                injected.remove(i);
                Disposer.dispose(oldDocument);
                continue;
            }
            oldFile.putUserData(FileContextUtil.INJECTED_IN_ELEMENT, injectedPsi.getUserData(FileContextUtil.INJECTED_IN_ELEMENT));
            assert shreds.isValid();
            if (!oldFile.textMatches(injectedPsi)) {
                oldViewProvider.performNonPhysically(() -> {
                    DebugUtil.startPsiModification("injected tree diff");
                    try {
                        final DiffLog diffLog = BlockSupportImpl.mergeTrees(oldFile, oldFileNode, injectedNode, new DaemonProgressIndicator(), oldFileNode.getText());
                        DocumentCommitThread.doActualPsiChange(oldFile, diffLog);
                    } finally {
                        DebugUtil.finishPsiModification();
                    }
                });
            }
            assert shreds.isValid();
            return oldFile;
        }
    }
    injected.add(documentWindow);
    return injectedPsi;
}
Also used : DocumentWindow(com.intellij.injected.editor.DocumentWindow) DaemonProgressIndicator(com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator) DocumentWindowImpl(com.intellij.injected.editor.DocumentWindowImpl) PsiFileImpl(com.intellij.psi.impl.source.PsiFileImpl) ASTNode(com.intellij.lang.ASTNode) DiffLog(com.intellij.psi.impl.source.text.DiffLog)

Example 15 with DocumentWindow

use of com.intellij.injected.editor.DocumentWindow in project intellij-community by JetBrains.

the class CodeStyleManagerImpl method reformatNewlyAddedElement.

@Override
public void reformatNewlyAddedElement(@NotNull final ASTNode parent, @NotNull final ASTNode addedElement) throws IncorrectOperationException {
    LOG.assertTrue(addedElement.getTreeParent() == parent, "addedElement must be added to parent");
    final PsiElement psiElement = parent.getPsi();
    PsiFile containingFile = psiElement.getContainingFile();
    final FileViewProvider fileViewProvider = containingFile.getViewProvider();
    if (fileViewProvider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
        containingFile = fileViewProvider.getPsi(fileViewProvider.getBaseLanguage());
    }
    TextRange textRange = addedElement.getTextRange();
    final Document document = fileViewProvider.getDocument();
    if (document instanceof DocumentWindow) {
        containingFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getTopLevelFile(containingFile);
        textRange = ((DocumentWindow) document).injectedToHost(textRange);
    }
    final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(containingFile);
    if (builder != null) {
        final FormattingModel model = CoreFormatterUtil.buildModel(builder, containingFile, getSettings(), FormattingMode.REFORMAT);
        FormatterEx.getInstanceEx().formatAroundRange(model, getSettings(), containingFile, textRange);
    }
    adjustLineIndent(containingFile, textRange);
}
Also used : DocumentWindow(com.intellij.injected.editor.DocumentWindow) TextRange(com.intellij.openapi.util.TextRange)

Aggregations

DocumentWindow (com.intellij.injected.editor.DocumentWindow)42 TextRange (com.intellij.openapi.util.TextRange)18 Document (com.intellij.openapi.editor.Document)17 NotNull (org.jetbrains.annotations.NotNull)11 Nullable (org.jetbrains.annotations.Nullable)9 Project (com.intellij.openapi.project.Project)8 VirtualFileWindow (com.intellij.injected.editor.VirtualFileWindow)6 VirtualFile (com.intellij.openapi.vfs.VirtualFile)6 PsiFile (com.intellij.psi.PsiFile)6 InjectedLanguageManager (com.intellij.lang.injection.InjectedLanguageManager)5 DocumentWindowImpl (com.intellij.injected.editor.DocumentWindowImpl)4 Language (com.intellij.lang.Language)4 Editor (com.intellij.openapi.editor.Editor)4 Segment (com.intellij.openapi.util.Segment)4 PsiFileImpl (com.intellij.psi.impl.source.PsiFileImpl)4 DaemonProgressIndicator (com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator)3 ASTNode (com.intellij.lang.ASTNode)3 com.intellij.psi (com.intellij.psi)3 PsiElement (com.intellij.psi.PsiElement)3 PsiDocumentManagerBase (com.intellij.psi.impl.PsiDocumentManagerBase)3