Search in sources :

Example 21 with LineRange

use of com.intellij.codeInsight.editorActions.moveUpDown.LineRange in project kotlin by JetBrains.

the class KotlinDeclarationMover method getTargetRange.

@Nullable
private static LineRange getTargetRange(@NotNull Editor editor, @NotNull PsiElement sibling, boolean down, @NotNull PsiElement target) {
    PsiElement start = sibling;
    PsiElement end = sibling;
    PsiElement nextParent = null;
    // moving out of code block
    if (sibling.getNode().getElementType() == (down ? KtTokens.RBRACE : KtTokens.LBRACE)) {
        // elements which aren't immediately placed in class body can't leave the block
        PsiElement parent = sibling.getParent();
        if (!(parent instanceof KtClassBody))
            return null;
        if (target instanceof KtEnumEntry)
            return null;
        KtClassOrObject ktClassOrObject = (KtClassOrObject) parent.getParent();
        assert ktClassOrObject != null;
        nextParent = ktClassOrObject.getParent();
        if (!down) {
            start = ktClassOrObject;
        }
    } else // moving into code block
    // element may move only into class body
    {
        if (sibling instanceof KtClassOrObject) {
            KtClassOrObject ktClassOrObject = (KtClassOrObject) sibling;
            KtClassBody classBody = ktClassOrObject.getBody();
            // confined elements can't leave their block
            if (classBody != null) {
                nextParent = classBody;
                if (!down) {
                    start = classBody.getRBrace();
                }
                end = down ? classBody.getLBrace() : classBody.getRBrace();
            }
        }
    }
    if (nextParent != null) {
        if (target instanceof KtAnonymousInitializer && !(nextParent instanceof KtClassBody))
            return null;
        if (target instanceof KtEnumEntry) {
            if (!(nextParent instanceof KtClassBody))
                return null;
            KtClassOrObject nextClassOrObject = (KtClassOrObject) nextParent.getParent();
            assert nextClassOrObject != null;
            if (!nextClassOrObject.hasModifier(KtTokens.ENUM_KEYWORD))
                return null;
        }
    }
    if (target instanceof KtPropertyAccessor && !(sibling instanceof KtPropertyAccessor))
        return null;
    return start != null && end != null ? new LineRange(start, end, editor.getDocument()) : null;
}
Also used : LineRange(com.intellij.codeInsight.editorActions.moveUpDown.LineRange) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 22 with LineRange

use of com.intellij.codeInsight.editorActions.moveUpDown.LineRange in project kotlin by JetBrains.

the class KotlinExpressionMover method checkForMovableDownClosingBrace.

private static BraceStatus checkForMovableDownClosingBrace(@NotNull PsiElement closingBrace, @NotNull PsiElement block, @NotNull Editor editor, @NotNull MoveInfo info) {
    PsiElement current = block;
    PsiElement nextElement = null;
    PsiElement nextExpression = null;
    do {
        PsiElement sibling = firstNonWhiteElement(current.getNextSibling(), true);
        if (sibling != null && nextElement == null) {
            nextElement = sibling;
        }
        if (sibling instanceof KtExpression) {
            nextExpression = sibling;
            break;
        }
        current = current.getParent();
    } while (current != null && !(PsiTreeUtil.instanceOf(current, BLOCKLIKE_ELEMENT_CLASSES)));
    if (nextExpression == null)
        return BraceStatus.NOT_MOVABLE;
    Document doc = editor.getDocument();
    info.toMove = new LineRange(closingBrace, closingBrace, doc);
    info.toMove2 = new LineRange(nextElement, nextExpression);
    info.indentSource = true;
    return BraceStatus.MOVABLE;
}
Also used : Document(com.intellij.openapi.editor.Document) LineRange(com.intellij.codeInsight.editorActions.moveUpDown.LineRange)

Example 23 with LineRange

use of com.intellij.codeInsight.editorActions.moveUpDown.LineRange in project kotlin by JetBrains.

the class AbstractKotlinUpDownMover method getSourceRange.

@Nullable
protected LineRange getSourceRange(@NotNull PsiElement firstElement, @NotNull PsiElement lastElement, @NotNull Editor editor, LineRange oldRange) {
    PsiElement parent = PsiTreeUtil.findCommonParent(firstElement, lastElement);
    int topExtension = 0;
    int bottomExtension = 0;
    if (parent instanceof KtFunctionLiteral) {
        KtBlockExpression block = ((KtFunctionLiteral) parent).getBodyExpression();
        if (block != null) {
            PsiElement comment = null;
            boolean extendDown = false;
            if (checkCommentAtBlockBound(firstElement, lastElement, block)) {
                comment = lastElement;
                extendDown = true;
                lastElement = block.getLastChild();
            } else if (checkCommentAtBlockBound(lastElement, firstElement, block)) {
                comment = firstElement;
                firstElement = block.getFirstChild();
            }
            if (comment != null) {
                int extension = KotlinRefactoringUtilKt.getLineCount(comment);
                if (extendDown) {
                    bottomExtension = extension;
                } else {
                    topExtension = extension;
                }
            }
            parent = PsiTreeUtil.findCommonParent(firstElement, lastElement);
        }
    }
    if (parent == null)
        return null;
    Pair<PsiElement, PsiElement> originalRange = getElementRange(parent, firstElement, lastElement);
    if (!checkSourceElement(originalRange.first) || !checkSourceElement(originalRange.second))
        return null;
    LineRange lineRange1 = getElementSourceLineRange(originalRange.first, editor, oldRange);
    if (lineRange1 == null)
        return null;
    LineRange lineRange2 = getElementSourceLineRange(originalRange.second, editor, oldRange);
    if (lineRange2 == null)
        return null;
    LineRange parentLineRange = getElementSourceLineRange(parent, editor, oldRange);
    LineRange sourceRange = new LineRange(lineRange1.startLine - topExtension, lineRange2.endLine + bottomExtension);
    if (parentLineRange != null && sourceRange.startLine == parentLineRange.startLine && sourceRange.endLine == parentLineRange.endLine) {
        sourceRange.firstElement = sourceRange.lastElement = parent;
    } else {
        sourceRange.firstElement = originalRange.first;
        sourceRange.lastElement = originalRange.second;
    }
    return sourceRange;
}
Also used : KtFunctionLiteral(org.jetbrains.kotlin.psi.KtFunctionLiteral) KtBlockExpression(org.jetbrains.kotlin.psi.KtBlockExpression) LineRange(com.intellij.codeInsight.editorActions.moveUpDown.LineRange) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 24 with LineRange

use of com.intellij.codeInsight.editorActions.moveUpDown.LineRange in project intellij-plugins by JetBrains.

the class DartStatementMover method calcInsertOffset.

private boolean calcInsertOffset(@NotNull PsiFile file, @NotNull Editor editor, @NotNull LineRange range, @NotNull final MoveInfo info, final boolean down) {
    int destLine = getDestLineForAnon(editor, range, down);
    int startLine = down ? range.endLine : range.startLine - 1;
    if (destLine < 0 || startLine < 0)
        return false;
    boolean firstTime = true;
    boolean isExpr = isMovingExpr(info.toMove);
    PsiElement elementStart = null;
    if (isExpr) {
        int offset = editor.logicalPositionToOffset(new LogicalPosition(startLine, 0));
        elementStart = firstNonWhiteMovableElement(offset, file, true);
        if (elementStart instanceof DartArgumentList) {
            elementStart = elementStart.getFirstChild();
        } else if (isRightBracket(elementStart) && info.toMove.firstElement instanceof DartNamedArgument) {
            // Possibly a named arg with list value
            elementStart = elementStart.getParent().getParent();
        }
        if (elementStart instanceof DartExpression || elementStart instanceof DartNamedArgument) {
            TextRange elementTextRange = elementStart.getTextRange();
            LogicalPosition pos = editor.offsetToLogicalPosition(elementTextRange.getEndOffset());
            int endOffset = editor.logicalPositionToOffset(new LogicalPosition(pos.line + 1, 0));
            PsiElement elementEnd = firstNonWhiteMovableElement(endOffset, file, false);
            if (elementEnd instanceof DartArgumentList && elementStart instanceof DartNamedArgument) {
                elementEnd = elementEnd.getLastChild();
                if (!isComma(elementEnd)) {
                    // Require trailing comma
                    return false;
                } else {
                    info.toMove2 = new LineRange(startLine, pos.line + 1);
                    return true;
                }
            }
            if (elementEnd != null && isComma(elementEnd)) {
                PsiElement elementTail = UsefulPsiTreeUtil.getPrevSiblingSkipWhiteSpacesAndComments(elementEnd, true);
                if (elementTail instanceof DartExpressionList) {
                    elementTail = elementTail.getLastChild();
                }
                if (elementStart == elementTail) {
                    if (down) {
                        info.toMove2 = new LineRange(startLine, pos.line + 1);
                    } else {
                        destLine = pos.line;
                        elementTextRange = elementTail.getTextRange();
                        pos = editor.offsetToLogicalPosition(elementTextRange.getStartOffset());
                        info.toMove2 = new LineRange(pos.line, destLine + 1);
                    }
                    return true;
                }
            }
        } else if (elementStart != null && isRightParen(elementStart)) {
            PsiElement start = elementStart.getParent().getParent();
            TextRange elementTextRange = start.getTextRange();
            LogicalPosition pos = editor.offsetToLogicalPosition(elementTextRange.getStartOffset());
            int startOffset = editor.logicalPositionToOffset(new LogicalPosition(pos.line, 0));
            PsiElement startElement = firstNonWhiteMovableElement(startOffset, file, true);
            if (startElement == start) {
                info.toMove2 = new LineRange(pos.line, down ? startLine : startLine + 1);
                return true;
            }
        }
    }
    while (true) {
        int offset = editor.logicalPositionToOffset(new LogicalPosition(destLine, 0));
        PsiElement element = firstNonWhiteMovableElement(offset, file, !isExpr || !down);
        if (firstTime) {
            if (element != null && element.getNode().getElementType() == (down ? DartTokenTypes.RBRACE : DartTokenTypes.LBRACE)) {
                PsiElement elementParent = element.getParent();
                if (elementParent != null && (isStatement(elementParent) || elementParent instanceof DartBlock)) {
                    return true;
                }
            }
        }
        if (element instanceof DartStatements)
            element = element.getFirstChild();
        while (element != null && !(element instanceof PsiFile)) {
            TextRange elementTextRange = element.getTextRange();
            if (elementTextRange.isEmpty() || !elementTextRange.grown(-1).shiftRight(1).contains(offset)) {
                PsiElement elementToSurround = null;
                boolean found = false;
                if (isExpr) {
                    if (firstTime && element instanceof DartExpression) {
                        found = true;
                    } else if (isComma(element) && UsefulPsiTreeUtil.getPrevSiblingSkipWhiteSpacesAndComments(element, true) == elementStart) {
                        found = true;
                    } else if (element instanceof DartArgumentList) {
                        element = element.getParent();
                        if (element.getParent() == elementStart) {
                            element = element.getParent().getNextSibling();
                            boolean hasComma = false;
                            while (element != null) {
                                if (UsefulPsiTreeUtil.isWhitespaceOrComment(element)) {
                                    if (element.getText().contains("\n")) {
                                        destLine += 1;
                                        break;
                                    }
                                } else if (isComma(element)) {
                                    hasComma = true;
                                } else {
                                    break;
                                }
                                element = element.getNextSibling();
                            }
                            if (!hasComma) {
                                // Disallow move if following expr has no trailing comma
                                return false;
                            }
                            found = true;
                        }
                    }
                } else if ((isStatement(element) || element instanceof PsiComment) && statementCanBePlacedAlong(element)) {
                    found = true;
                    if (!(element.getParent() instanceof IDartBlock)) {
                        elementToSurround = element;
                    }
                } else if ((element.getNode().getElementType() == DartTokenTypes.RBRACE && element.getParent() instanceof IDartBlock && (!isStatement(element.getParent().getParent()) || statementCanBePlacedAlong(element.getParent().getParent()))) || (!down && element instanceof DartStatements)) {
                    // Before/after code block closing/opening brace.
                    found = true;
                }
                if (found) {
                    if (elementToSurround != null) {
                        final SmartPointerManager manager = SmartPointerManager.getInstance(elementToSurround.getProject());
                        statementToSurroundWithCodeBlock = manager.createSmartPsiElementPointer(elementToSurround);
                    }
                    info.toMove = range;
                    int endLine = destLine;
                    if (startLine > endLine) {
                        int tmp = endLine;
                        endLine = startLine;
                        startLine = tmp;
                    }
                    info.toMove2 = new LineRange(startLine, down ? endLine : endLine + 1);
                    return true;
                }
            }
            element = element.getParent();
        }
        firstTime = false;
        destLine += down ? 1 : -1;
        if (destLine <= 0 || destLine >= editor.getDocument().getLineCount()) {
            return false;
        }
    }
}
Also used : LogicalPosition(com.intellij.openapi.editor.LogicalPosition) TextRange(com.intellij.openapi.util.TextRange) LineRange(com.intellij.codeInsight.editorActions.moveUpDown.LineRange) LeafPsiElement(com.intellij.psi.impl.source.tree.LeafPsiElement)

Aggregations

LineRange (com.intellij.codeInsight.editorActions.moveUpDown.LineRange)24 Document (com.intellij.openapi.editor.Document)8 PsiElement (com.intellij.psi.PsiElement)8 Nullable (org.jetbrains.annotations.Nullable)6 LeafPsiElement (com.intellij.psi.impl.source.tree.LeafPsiElement)4 TextRange (com.intellij.openapi.util.TextRange)3 LogicalPosition (com.intellij.openapi.editor.LogicalPosition)2 PsiComment (com.intellij.psi.PsiComment)2 GroovyFileBase (org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase)2 GroovyPsiElement (org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement)2 GrTypeDefinition (org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition)2 CaretModel (com.intellij.openapi.editor.CaretModel)1 SelectionModel (com.intellij.openapi.editor.SelectionModel)1 Project (com.intellij.openapi.project.Project)1 PsiRecursiveElementVisitor (com.intellij.psi.PsiRecursiveElementVisitor)1 ArrayList (java.util.ArrayList)1 KtBlockExpression (org.jetbrains.kotlin.psi.KtBlockExpression)1 KtFunctionLiteral (org.jetbrains.kotlin.psi.KtFunctionLiteral)1 GrVariableDeclaration (org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration)1 GrCodeBlock (org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock)1