in Dart/src/com/jetbrains/lang/dart/ide/moveCode/DartStatementMover.java [229:387]
private boolean calcInsertOffset(@NotNull PsiFile file,
@NotNull Editor editor,
@NotNull LineRange range,
final @NotNull 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) {
elementStart = elementStart.getParent().getParent(); // Possibly a named arg with list value
}
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)) {
return false; // Require trailing comma
}
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) {
return false; // Disallow move if following expr has no trailing comma
}
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;
}
}
}