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;
}
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;
}
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;
}
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;
}
}
}
Aggregations