Search in sources :

Example 71 with Document

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

the class XmlMover method checkAvailable.

//private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.actions.moveUpDown.XmlMover");
@Override
public boolean checkAvailable(@NotNull final Editor editor, @NotNull final PsiFile file, @NotNull final MoveInfo info, final boolean down) {
    if (!(file instanceof XmlFile)) {
        return false;
    }
    if (!super.checkAvailable(editor, file, info, down))
        return false;
    // updated moved range end to cover multiline tag start
    final Document document = editor.getDocument();
    int movedLineStart = document.getLineStartOffset(info.toMove.startLine);
    final int movedLineEnd = document.getLineEndOffset(info.toMove.endLine - 1);
    PsiElement movedEndElement = file.findElementAt(movedLineEnd);
    if (movedEndElement instanceof PsiWhiteSpace)
        movedEndElement = PsiTreeUtil.prevLeaf(movedEndElement);
    PsiElement movedStartElement = file.findElementAt(movedLineStart);
    if (movedStartElement instanceof PsiWhiteSpace)
        movedStartElement = PsiTreeUtil.nextLeaf(movedStartElement);
    if (movedEndElement == null || movedStartElement == null)
        return false;
    final PsiNamedElement namedParentAtEnd = PsiTreeUtil.getParentOfType(movedEndElement, PsiNamedElement.class);
    final PsiNamedElement namedParentAtStart = PsiTreeUtil.getParentOfType(movedStartElement, PsiNamedElement.class);
    if (checkInjections(movedEndElement, movedStartElement))
        return false;
    PsiNamedElement movedParent = null;
    if (namedParentAtEnd == namedParentAtStart)
        movedParent = namedParentAtEnd;
    else if (namedParentAtEnd instanceof XmlAttribute && namedParentAtStart instanceof XmlTag && namedParentAtEnd.getParent() == namedParentAtStart) {
        movedParent = namedParentAtStart;
    } else if (namedParentAtStart instanceof XmlAttribute && namedParentAtEnd instanceof XmlTag && namedParentAtStart.getParent() == namedParentAtEnd) {
        movedParent = namedParentAtEnd;
    }
    if (movedParent == null) {
        return false;
    }
    final TextRange textRange = movedParent.getTextRange();
    if (movedParent instanceof XmlTag) {
        final XmlTag tag = (XmlTag) movedParent;
        PsiElement parent = tag.getParent();
        if (!(parent instanceof XmlTag) && PsiTreeUtil.getChildrenOfType(parent, XmlTag.class).length < 2) {
            // the only top-level tag
            return info.prohibitMove();
        }
        final TextRange valueRange = tag.getValue().getTextRange();
        final int valueStart = valueRange.getStartOffset();
        if (HtmlUtil.isHtmlTag(tag) && (HtmlUtil.isScriptTag(tag) || HtmlUtil.STYLE_TAG_NAME.equals(tag.getName()))) {
            info.toMove = new LineRange(tag);
            int nextLine = down ? info.toMove.endLine : info.toMove.startLine - 1;
            info.toMove2 = new LineRange(nextLine, nextLine + 1);
        }
        if (movedLineStart < valueStart && valueStart + 1 < document.getTextLength()) {
            movedLineStart = updateMovedRegionEnd(document, movedLineStart, valueStart + 1, info, down);
        }
        if (movedLineStart < valueStart) {
            movedLineStart = updateMovedRegionStart(document, movedLineStart, tag.getTextRange().getStartOffset(), info, down);
        }
    } else if (movedParent instanceof XmlAttribute) {
        final int endOffset = textRange.getEndOffset() + 1;
        if (endOffset < document.getTextLength())
            movedLineStart = updateMovedRegionEnd(document, movedLineStart, endOffset, info, down);
        movedLineStart = updateMovedRegionStart(document, movedLineStart, textRange.getStartOffset(), info, down);
    }
    final TextRange moveDestinationRange = new UnfairTextRange(document.getLineStartOffset(info.toMove2.startLine), document.getLineEndOffset(info.toMove2.endLine - 1));
    if (movedParent instanceof XmlAttribute) {
        final XmlTag parent = ((XmlAttribute) movedParent).getParent();
        if (parent != null) {
            final TextRange valueRange = parent.getValue().getTextRange();
            // Do not move attributes out of tags
            if ((down && moveDestinationRange.getEndOffset() >= valueRange.getStartOffset()) || (!down && moveDestinationRange.getStartOffset() <= parent.getTextRange().getStartOffset())) {
                return info.prohibitMove();
            }
        }
    }
    if (down) {
        PsiElement updatedElement = file.findElementAt(moveDestinationRange.getEndOffset());
        if (updatedElement instanceof PsiWhiteSpace)
            updatedElement = PsiTreeUtil.prevLeaf(updatedElement);
        if (updatedElement != null) {
            final PsiNamedElement targetParent = PsiTreeUtil.getParentOfType(updatedElement, movedParent.getClass());
            if (targetParent instanceof XmlTag) {
                if (targetParent == movedParent)
                    return false;
                if (moveTags(info, (XmlTag) movedParent, (XmlTag) targetParent, down))
                    return true;
                final XmlTag tag = (XmlTag) targetParent;
                final int offset = tag.isEmpty() ? tag.getTextRange().getStartOffset() : tag.getValue().getTextRange().getStartOffset();
                updatedMovedIntoEnd(document, info, offset);
                if (tag.isEmpty()) {
                    info.toMove2 = new LineRange(targetParent);
                }
            } else if (targetParent instanceof XmlAttribute) {
                updatedMovedIntoEnd(document, info, targetParent.getTextRange().getEndOffset());
            }
        }
    } else {
        PsiElement updatedElement = file.findElementAt(moveDestinationRange.getStartOffset());
        if (updatedElement instanceof PsiWhiteSpace)
            updatedElement = PsiTreeUtil.nextLeaf(updatedElement);
        if (updatedElement != null) {
            final PsiNamedElement targetParent = PsiTreeUtil.getParentOfType(updatedElement, movedParent.getClass());
            if (targetParent instanceof XmlTag) {
                final XmlTag tag = (XmlTag) targetParent;
                final TextRange tagValueRange = tag.getValue().getTextRange();
                // We need to update destination range to jump over tag start
                final XmlTag[] subtags = tag.getSubTags();
                if ((tagValueRange.contains(movedLineStart) && subtags.length > 0 && subtags[0] == movedParent) || (tagValueRange.getLength() == 0 && tag.getTextRange().intersects(moveDestinationRange))) {
                    final int line = document.getLineNumber(tag.getTextRange().getStartOffset());
                    final LineRange toMove2 = info.toMove2;
                    info.toMove2 = new LineRange(Math.min(line, toMove2.startLine), toMove2.endLine);
                }
                if (targetParent == movedParent)
                    return false;
                if (moveTags(info, (XmlTag) movedParent, (XmlTag) targetParent, down))
                    return true;
            } else if (targetParent instanceof XmlAttribute) {
                final int line = document.getLineNumber(targetParent.getTextRange().getStartOffset());
                final LineRange toMove2 = info.toMove2;
                info.toMove2 = new LineRange(Math.min(line, toMove2.startLine), toMove2.endLine);
            }
        }
    }
    if (movedParent instanceof XmlTag) {
        // it's quite simple after all...
        info.toMove = new LineRange(movedParent);
    }
    return true;
}
Also used : UnfairTextRange(com.intellij.openapi.util.UnfairTextRange) PsiNamedElement(com.intellij.psi.PsiNamedElement) TextRange(com.intellij.openapi.util.TextRange) UnfairTextRange(com.intellij.openapi.util.UnfairTextRange) Document(com.intellij.openapi.editor.Document) PsiElement(com.intellij.psi.PsiElement) PsiWhiteSpace(com.intellij.psi.PsiWhiteSpace)

Example 72 with Document

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

the class GenerationNode method generate.

@NotNull
public TemplateImpl generate(@NotNull CustomTemplateCallback callback, @Nullable ZenCodingGenerator generator, @NotNull Collection<ZenCodingFilter> filters, boolean insertSurroundedText, int segmentsLimit) {
    myContainsSurroundedTextMarker = !(insertSurroundedText && myInsertSurroundedTextAtTheEnd);
    GenerationNode generationNode = this;
    if (generationNode != this) {
        return generationNode.generate(callback, generator, Collections.emptyList(), insertSurroundedText, segmentsLimit);
    }
    boolean shouldNotReformatTemplate = false;
    boolean oneLineTemplateExpanding = false;
    for (ZenCodingFilter filter : filters) {
        generationNode = filter.filterNode(generationNode);
        if (filter instanceof SingleLineEmmetFilter) {
            shouldNotReformatTemplate = true;
            oneLineTemplateExpanding = true;
        }
    }
    CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(callback.getProject());
    String indentStr;
    if (callback.isInInjectedFragment()) {
        Editor editor = callback.getEditor();
        Document document = editor.getDocument();
        if (document instanceof DocumentWindowImpl && ((DocumentWindowImpl) document).isOneLine()) {
            /* 
         * If document is one-line that in the moment of inserting text,
         * new line chars will be filtered (see DocumentWindowImpl#insertString).
         * So in this case we should filter text by SingleLineAvoid in order to avoid
         * inconsistency of template segments.
         */
            oneLineTemplateExpanding = true;
            filters.add(new SingleLineEmmetFilter());
        }
        indentStr = "";
    } else if (settings.useTabCharacter(callback.getFileType())) {
        indentStr = "\t";
    } else {
        int tabSize = settings.getTabSize(callback.getFileType());
        indentStr = StringUtil.repeatSymbol(' ', tabSize);
    }
    LiveTemplateBuilder builder = new LiveTemplateBuilder(EmmetOptions.getInstance().isAddEditPointAtTheEndOfTemplate(), segmentsLimit);
    int end = -1;
    boolean hasChildren = myChildren.size() > 0;
    TemplateImpl parentTemplate;
    Map<String, String> predefinedValues;
    if (generator instanceof XmlZenCodingGenerator) {
        TemplateToken xmlTemplateToken = myTemplateToken;
        parentTemplate = invokeXmlTemplate(xmlTemplateToken, callback, generator, hasChildren);
        predefinedValues = buildPredefinedValues(xmlTemplateToken.getAttributes(), (XmlZenCodingGenerator) generator, hasChildren);
    } else {
        parentTemplate = invokeTemplate(myTemplateToken, hasChildren, callback, generator);
        predefinedValues = null;
    }
    String s = parentTemplate.getString();
    for (ZenCodingFilter filter : filters) {
        s = filter.filterText(s, myTemplateToken);
    }
    parentTemplate = parentTemplate.copy();
    parentTemplate.setString(s);
    final String txt = hasChildren || myContainsSurroundedTextMarker ? null : mySurroundedText;
    parentTemplate = expandTemplate(parentTemplate, predefinedValues, txt, segmentsLimit);
    int offset = builder.insertTemplate(0, parentTemplate, null);
    int newOffset = gotoChild(callback.getProject(), builder.getText(), offset, 0, builder.length());
    if (offset < builder.length() && newOffset != offset) {
        end = offset;
    }
    offset = newOffset;
    if (end == -1 && offset < builder.length() && myChildren.size() == 0) {
        end = offset;
    }
    LiveTemplateBuilder.Marker marker = offset < builder.length() ? builder.createMarker(offset) : null;
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0, myChildrenSize = myChildren.size(); i < myChildrenSize; i++) {
        GenerationNode child = myChildren.get(i);
        TemplateImpl childTemplate = child.generate(callback, generator, filters, !myContainsSurroundedTextMarker, segmentsLimit);
        boolean blockTag = child.isBlockTag();
        if (!oneLineTemplateExpanding && blockTag && !isNewLineBefore(builder.getText(), offset)) {
            builder.insertText(offset, "\n" + indentStr, false);
            offset += indentStr.length() + 1;
        }
        int e = builder.insertTemplate(offset, childTemplate, null);
        offset = marker != null ? marker.getEndOffset() : builder.length();
        if (!oneLineTemplateExpanding && ((blockTag && !isNewLineAfter(builder.getText(), offset)) || myInsertNewLineBetweenNodes)) {
            builder.insertText(offset, "\n" + indentStr, false);
            offset += indentStr.length() + 1;
        }
        if (end == -1 && e < offset) {
            end = e;
        }
    }
    if (shouldNotReformatTemplate) {
        builder.setIsToReformat(false);
    }
    return builder.buildTemplate();
}
Also used : TemplateImpl(com.intellij.codeInsight.template.impl.TemplateImpl) XmlZenCodingGenerator(com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGenerator) SingleLineEmmetFilter(com.intellij.codeInsight.template.emmet.filters.SingleLineEmmetFilter) Document(com.intellij.openapi.editor.Document) ZenCodingFilter(com.intellij.codeInsight.template.emmet.filters.ZenCodingFilter) CodeStyleSettings(com.intellij.psi.codeStyle.CodeStyleSettings) DocumentWindowImpl(com.intellij.injected.editor.DocumentWindowImpl) TemplateToken(com.intellij.codeInsight.template.emmet.tokens.TemplateToken) Editor(com.intellij.openapi.editor.Editor) LiveTemplateBuilder(com.intellij.codeInsight.template.LiveTemplateBuilder) NotNull(org.jetbrains.annotations.NotNull)

Example 73 with Document

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

the class GroovyInsertHandler method handleInsert.

@Override
public void handleInsert(InsertionContext context, LookupElement item) {
    @NonNls Object obj = item.getObject();
    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    if (obj instanceof GroovyResolveResult) {
        substitutor = ((GroovyResolveResult) obj).getSubstitutor();
        obj = ((GroovyResolveResult) obj).getElement();
    }
    if (obj instanceof PsiMethod) {
        final PsiMethod method = (PsiMethod) obj;
        PsiParameter[] parameters = method.getParameterList().getParameters();
        Editor editor = context.getEditor();
        Document document = editor.getDocument();
        if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
            handleOverwrite(editor.getCaretModel().getOffset(), document);
        }
        CaretModel caretModel = editor.getCaretModel();
        int offset = context.getTailOffset();
        PsiFile file = context.getFile();
        PsiElement elementAt = file.findElementAt(context.getStartOffset());
        assert elementAt != null;
        PsiElement parent = elementAt.getParent();
        if (parent instanceof GrReferenceExpression && ((GrReferenceExpression) parent).getDotTokenType() == GroovyTokenTypes.mMEMBER_POINTER) {
            return;
        }
        CharSequence charsSequence = document.getCharsSequence();
        if (isAnnotationNameValuePair(obj, parent)) {
            int endOffset = offset;
            if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) {
                endOffset = CharArrayUtil.shiftForward(charsSequence, offset, " \t");
                if (charsSequence.length() > endOffset && charsSequence.charAt(endOffset) == '=') {
                    endOffset++;
                    endOffset = CharArrayUtil.shiftForward(charsSequence, endOffset, " \t");
                }
            }
            document.replaceString(offset, endOffset, " = ");
            caretModel.moveToOffset(offset + 3);
            return;
        }
        if (PsiTreeUtil.getParentOfType(elementAt, GrImportStatement.class) != null)
            return;
        if (parameters.length == 1) {
            if ((context.getCompletionChar() != '(' && context.getCompletionChar() != ' ') && TypesUtil.isClassType(parameters[0].getType(), GroovyCommonClassNames.GROOVY_LANG_CLOSURE)) {
                int afterBrace;
                final int nonWs = CharArrayUtil.shiftForward(charsSequence, offset, " \t");
                if (nonWs < document.getTextLength() && charsSequence.charAt(nonWs) == '{') {
                    afterBrace = nonWs + 1;
                } else {
                    if (isSpaceBeforeClosure(file)) {
                        document.insertString(offset, " ");
                        offset++;
                    }
                    if (ClosureCompleter.runClosureCompletion(context, method, substitutor, document, offset, parent))
                        return;
                    if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
                        //smart enter invoked
                        document.insertString(offset, "{\n}");
                        //position caret before '{' for smart enter
                        afterBrace = offset + 1;
                        context.setTailOffset(afterBrace);
                    } else {
                        document.insertString(offset, "{}");
                        afterBrace = offset + 1;
                    }
                }
                caretModel.moveToOffset(afterBrace);
                return;
            }
        }
        context.commitDocument();
        if (context.getCompletionChar() == ' ' && MethodParenthesesHandler.hasParams(item, context.getElements(), true, method)) {
            return;
        }
        CommonCodeStyleSettings settings = context.getCodeStyleSettings();
        ParenthesesInsertHandler.getInstance(MethodParenthesesHandler.hasParams(item, context.getElements(), true, method), settings.SPACE_BEFORE_METHOD_CALL_PARENTHESES, settings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, true, true).handleInsert(context, item);
        AutoPopupController.getInstance(context.getProject()).autoPopupParameterInfo(editor, method);
        return;
    }
    if (obj instanceof PsiClass) {
        final PsiClass clazz = (PsiClass) obj;
        Editor editor = context.getEditor();
        Document document = editor.getDocument();
        PsiFile file = PsiDocumentManager.getInstance(clazz.getProject()).getPsiFile(document);
        assert file != null;
        PsiElement elementAt = file.findElementAt(context.getStartOffset());
        assert elementAt != null;
        CaretModel caretModel = editor.getCaretModel();
        int offset = context.getStartOffset() + elementAt.getTextLength();
        final String text = document.getText();
        final PsiElement parent = elementAt.getParent();
        if (parent instanceof GrCodeReferenceElement && parent.getParent() instanceof GrNewExpression && (offset == text.length() || !text.substring(offset).trim().startsWith("("))) {
            document.insertString(offset, "()");
            if (GroovyCompletionUtil.hasConstructorParameters(clazz, parent)) {
                caretModel.moveToOffset(offset + 1);
                return;
            }
            caretModel.moveToOffset(offset + 2);
            return;
        }
    }
    if (context.getCompletionChar() == '=') {
        context.setAddCompletionChar(false);
        TailType.EQ.processTail(context.getEditor(), context.getTailOffset());
        return;
    }
    if (obj instanceof PsiPackage) {
        AutoPopupController.getInstance(context.getProject()).scheduleAutoPopup(context.getEditor());
    }
}
Also used : NonNls(org.jetbrains.annotations.NonNls) CaretModel(com.intellij.openapi.editor.CaretModel) Document(com.intellij.openapi.editor.Document) GrImportStatement(org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement) GrReferenceExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression) GrNewExpression(org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression) GrCodeReferenceElement(org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement) GroovyResolveResult(org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult) CommonCodeStyleSettings(com.intellij.psi.codeStyle.CommonCodeStyleSettings) Editor(com.intellij.openapi.editor.Editor)

Example 74 with Document

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

the class GrFinalListener method perform.

public void perform(final boolean generateFinal, final String modifier, final GrVariable variable) {
    final Document document = myEditor.getDocument();
    LOG.assertTrue(variable != null);
    final GrModifierList modifierList = variable.getModifierList();
    LOG.assertTrue(modifierList != null);
    final int textOffset = modifierList.getTextOffset();
    final Runnable runnable = () -> {
        if (generateFinal) {
            final GrTypeElement typeElement = variable.getTypeElementGroovy();
            final int typeOffset = typeElement != null ? typeElement.getTextOffset() : textOffset;
            document.insertString(typeOffset, modifier + " ");
        } else {
            final int idx = modifierList.getText().indexOf(modifier);
            document.deleteString(textOffset + idx, textOffset + idx + modifier.length() + 1);
        }
    };
    final LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor);
    if (lookup != null) {
        lookup.performGuardedChange(runnable);
    } else {
        runnable.run();
    }
    PsiDocumentManager.getInstance(variable.getProject()).commitDocument(document);
}
Also used : GrModifierList(org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList) GrTypeElement(org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement) LookupImpl(com.intellij.codeInsight.lookup.impl.LookupImpl) Document(com.intellij.openapi.editor.Document)

Example 75 with Document

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

the class GroovyMethodInliner method reformatOwner.

private static void reformatOwner(@Nullable GrVariableDeclarationOwner owner) throws IncorrectOperationException {
    if (owner == null)
        return;
    PsiFile file = owner.getContainingFile();
    Project project = file.getProject();
    PsiDocumentManager manager = PsiDocumentManager.getInstance(project);
    Document document = manager.getDocument(file);
    if (document != null) {
        manager.doPostponedOperationsAndUnblockDocument(document);
        CodeStyleManager.getInstance(project).adjustLineIndent(file, owner.getTextRange());
    }
}
Also used : Project(com.intellij.openapi.project.Project) Document(com.intellij.openapi.editor.Document)

Aggregations

Document (com.intellij.openapi.editor.Document)1075 VirtualFile (com.intellij.openapi.vfs.VirtualFile)246 PsiFile (com.intellij.psi.PsiFile)191 Project (com.intellij.openapi.project.Project)164 NotNull (org.jetbrains.annotations.NotNull)138 Nullable (org.jetbrains.annotations.Nullable)129 TextRange (com.intellij.openapi.util.TextRange)122 PsiDocumentManager (com.intellij.psi.PsiDocumentManager)117 PsiElement (com.intellij.psi.PsiElement)107 Editor (com.intellij.openapi.editor.Editor)104 LightVirtualFile (com.intellij.testFramework.LightVirtualFile)56 FileDocumentManager (com.intellij.openapi.fileEditor.FileDocumentManager)45 IncorrectOperationException (com.intellij.util.IncorrectOperationException)43 IOException (java.io.IOException)42 RangeMarker (com.intellij.openapi.editor.RangeMarker)35 MockVirtualFile (com.intellij.mock.MockVirtualFile)33 File (java.io.File)32 ArrayList (java.util.ArrayList)32 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)30 List (java.util.List)29