mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-170464 "Move statement" messes up whitespace and comments around fields
fix moving through whitespace
This commit is contained in:
+38
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,13 +22,16 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspClassLevelDeclarationStatement;
|
||||
import com.intellij.psi.impl.source.tree.Factory;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -163,25 +166,45 @@ class DeclarationMover extends LineMover {
|
||||
}
|
||||
final boolean areWeMovingClass = range.firstElement instanceof PsiClass;
|
||||
info.toMove = range;
|
||||
try {
|
||||
LineRange intraClassRange = moveInsideOutsideClassPosition(editor, sibling, down, areWeMovingClass);
|
||||
if (intraClassRange == null) {
|
||||
info.toMove2 = new LineRange(sibling, sibling, document);
|
||||
if (down && sibling.getNextSibling() == null) return false;
|
||||
}
|
||||
else {
|
||||
info.toMove2 = intraClassRange;
|
||||
}
|
||||
if (down ? info.toMove2.startLine < info.toMove.endLine : info.toMove2.endLine > info.toMove.startLine) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int neibourghLine = down ? range.endLine : range.startLine - 1;
|
||||
if (neibourghLine >= 0 && neibourghLine < document.getLineCount() &&
|
||||
CharArrayUtil.containsOnlyWhiteSpaces(document.getImmutableCharSequence().subSequence(document.getLineStartOffset(neibourghLine),
|
||||
document.getLineEndOffset(neibourghLine))) &&
|
||||
emptyLineCanBeDeletedAccordingToCodeStyle(file, document, document.getLineEndOffset(neibourghLine))) {
|
||||
info.toMove2 = new LineRange(neibourghLine, neibourghLine + 1);
|
||||
}
|
||||
catch (IllegalMoveException e) {
|
||||
info.toMove2 = null;
|
||||
else {
|
||||
try {
|
||||
LineRange intraClassRange = moveInsideOutsideClassPosition(editor, sibling, down, areWeMovingClass);
|
||||
if (intraClassRange == null) {
|
||||
info.toMove2 = new LineRange(sibling, sibling, document);
|
||||
if (down && sibling.getNextSibling() == null) return false;
|
||||
}
|
||||
else {
|
||||
info.toMove2 = intraClassRange;
|
||||
}
|
||||
if (down ? info.toMove2.startLine < info.toMove.endLine : info.toMove2.endLine > info.toMove.startLine) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (IllegalMoveException e) {
|
||||
info.toMove2 = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean emptyLineCanBeDeletedAccordingToCodeStyle(PsiFile file, Document document, int offset) {
|
||||
CharSequence text = document.getImmutableCharSequence();
|
||||
String whitespace = " \t\n";
|
||||
int whitespaceStartOffset = CharArrayUtil.shiftBackward(text, offset - 1, whitespace) + 1;
|
||||
int whitespaceEndOffset = CharArrayUtil.shiftForward(text, offset, whitespace);
|
||||
int minLineFeeds = CodeStyleManager.getInstance(file.getProject()).getMinLineFeeds(file, whitespaceEndOffset);
|
||||
int actualLineFeeds = StringUtil.countNewLines(text.subSequence(whitespaceStartOffset, whitespaceEndOffset));
|
||||
return actualLineFeeds > minLineFeeds;
|
||||
}
|
||||
|
||||
private static LineRange memberRange(@NotNull PsiElement member, Editor editor, LineRange lineRange) {
|
||||
final TextRange textRange = member.getTextRange();
|
||||
if (editor.getDocument().getTextLength() < textRange.getEndOffset()) return null;
|
||||
|
||||
@@ -278,6 +278,15 @@ public abstract class CodeStyleManager {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates minimum number of line feeds that should precede block starting at given offset, as dictated by formatting model.
|
||||
* Returns <code>-1</code>, if required block cannot be found at provided offset,
|
||||
* or spacing cannot be calculated due to some other reason.
|
||||
*/
|
||||
public int getMinLineFeeds(@NotNull PsiFile file, int offset) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current formatting mode.
|
||||
*
|
||||
|
||||
@@ -132,6 +132,13 @@ public abstract class FormatterEx{
|
||||
* or spacing cannot be calculated due to some other reason.
|
||||
*/
|
||||
public abstract int getSpacingForBlockAtOffset(FormattingModel model, int offset);
|
||||
|
||||
/**
|
||||
* Calculates minimum number of line feeds that should precede block starting at given offset, as dictated by formatting model.
|
||||
* Returns <code>-1</code>, if required block cannot be found at provided offset,
|
||||
* or spacing cannot be calculated due to some other reason.
|
||||
*/
|
||||
public abstract int getMinLineFeedsBeforeBlockAtOffset(FormattingModel model, int offset);
|
||||
|
||||
public interface IndentInfoStorage {
|
||||
void saveIndentInfo(@Nullable IndentInfo info, int startOffset);
|
||||
|
||||
@@ -114,24 +114,39 @@ public class FormatterImpl extends FormatterEx
|
||||
|
||||
@Override
|
||||
public int getSpacingForBlockAtOffset(FormattingModel model, int offset) {
|
||||
SpacingImpl spacing = getSpacingBeforeBlockAtOffset(model, offset);
|
||||
if (spacing != null) {
|
||||
int minSpaces = spacing.getMinSpaces();
|
||||
if (minSpaces >= 0) {
|
||||
return minSpaces;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinLineFeedsBeforeBlockAtOffset(FormattingModel model, int offset) {
|
||||
SpacingImpl spacing = getSpacingBeforeBlockAtOffset(model, offset);
|
||||
if (spacing != null) {
|
||||
int minLineFeeds = spacing.getMinLineFeeds();
|
||||
if (minLineFeeds >= 0) {
|
||||
return minLineFeeds;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static SpacingImpl getSpacingBeforeBlockAtOffset(FormattingModel model, int offset) {
|
||||
Couple<Block> blockWithParent = getBlockAtOffset(null, model.getRootBlock(), offset);
|
||||
if (blockWithParent != null) {
|
||||
Block parentBlock = blockWithParent.first;
|
||||
Block targetBlock = blockWithParent.second;
|
||||
if (parentBlock != null && targetBlock != null) {
|
||||
Block prevBlock = findPreviousSibling(parentBlock, targetBlock);
|
||||
if (prevBlock != null) {
|
||||
SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
|
||||
if (spacing != null) {
|
||||
int minSpaces = spacing.getMinSpaces();
|
||||
if (minSpaces >= 0) {
|
||||
return minSpaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prevBlock != null) return (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+14
-3
@@ -883,10 +883,21 @@ public class CodeStyleManagerImpl extends CodeStyleManager implements Formatting
|
||||
|
||||
@Override
|
||||
public int getSpacing(@NotNull PsiFile file, int offset) {
|
||||
FormattingModel model = createFormattingModel(file);
|
||||
return model == null ? -1 : FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinLineFeeds(@NotNull PsiFile file, int offset) {
|
||||
FormattingModel model = createFormattingModel(file);
|
||||
return model == null ? -1 : FormatterEx.getInstance().getMinLineFeedsBeforeBlockAtOffset(model, offset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FormattingModel createFormattingModel(@NotNull PsiFile file) {
|
||||
FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
|
||||
if (builder == null) return -1;
|
||||
if (builder == null) return null;
|
||||
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
|
||||
FormattingModel model = builder.createModel(file, settings);
|
||||
return FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset);
|
||||
return builder.createModel(file, settings);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user