fixed PY-6994 Paste leads to syntactically incorrect code in case pasting copied text instead of selection

This commit is contained in:
Ekaterina Tuzova
2012-08-02 14:30:01 +04:00
parent 655b8f5913
commit 25c85acb6a
23 changed files with 192 additions and 18 deletions

View File

@@ -2,18 +2,17 @@ package com.jetbrains.python.editor;
import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor; import com.intellij.codeInsight.editorActions.CopyPastePreProcessor;
import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RawText;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.CharFilter;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore; import com.intellij.psi.util.PsiUtilCore;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyStringLiteralExpression; import com.jetbrains.python.psi.PyStringLiteralExpression;
@@ -52,7 +51,18 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
if (StringUtil.countChars(text, '\n') > 0 || StringUtil.startsWithWhitespace(text)) { //2, 3, 4 case from doc if (StringUtil.countChars(text, '\n') > 0 || StringUtil.startsWithWhitespace(text)) { //2, 3, 4 case from doc
final PsiElement element = PsiUtilCore.getElementAtOffset(file, caretOffset - 1); final PsiElement element = PsiUtilCore.getElementAtOffset(file, caretOffset - 1);
if (PsiTreeUtil.getParentOfType(element, PyStringLiteralExpression.class) != null) return text; if (PsiTreeUtil.getParentOfType(element, PyStringLiteralExpression.class) != null) return text;
caretModel.moveToOffset(lineStartOffset);
final SelectionModel selectionModel = editor.getSelectionModel();
if (selectionModel.getSelectionStart() != selectionModel.getSelectionEnd()) {
final int line = document.getLineNumber(selectionModel.getSelectionStart());
final int lineOffset = getLineStartSafeOffset(document, line);
final PsiElement ws = file.findElementAt(lineOffset);
int offset = ws instanceof PsiWhiteSpace? ws.getTextRange().getEndOffset() : lineOffset;
caretModel.moveToOffset(offset);
selectionModel.setSelection(offset, selectionModel.getSelectionEnd());
}
else
caretModel.moveToOffset(lineStartOffset);
String spaceString; String spaceString;
int indent = 0; int indent = 0;
@@ -69,12 +79,17 @@ public class PythonCopyPasteProcessor implements CopyPastePreProcessor {
if (indent < 0) if (indent < 0)
indent = StringUtil.isEmptyOrSpaces(spaceString) ? spaceString.length() : 0; indent = StringUtil.isEmptyOrSpaces(spaceString) ? spaceString.length() : 0;
final String trimmed = StringUtil.trimLeading(strings.get(0)); //decrease indent if needed if (indent == CodeStyleSettingsManager.getSettings(project).getIndentSize(PythonFileType.INSTANCE)) {
if (trimmed.startsWith("def ") || trimmed.startsWith("if ") || trimmed.startsWith("try:") || indent = 0;
trimmed.startsWith("class ") || trimmed.startsWith("for ") || trimmed.startsWith("elif ") || }
trimmed.startsWith("else:") || trimmed.startsWith("except") || trimmed.startsWith("while ")) { else {
indent = StringUtil.findFirst(spaceString, CharFilter.NOT_WHITESPACE_FILTER) / 2; final String trimmed = StringUtil.trimLeading(strings.get(0)); //decrease indent if needed
if (indent < 0) indent = 0; if (trimmed.startsWith("def ") || trimmed.startsWith("if ") || trimmed.startsWith("try:") ||
trimmed.startsWith("class ") || trimmed.startsWith("for ") || trimmed.startsWith("elif ") ||
trimmed.startsWith("else:") || trimmed.startsWith("except") || trimmed.startsWith("while ")) {
indent = StringUtil.findFirst(spaceString, CharFilter.NOT_WHITESPACE_FILTER) / 2;
if (indent < 0) indent = 0;
}
} }
} }
} }

View File

@@ -0,0 +1,9 @@
if True:
a = 1
b = 2
def f():
if True:
a = 1
b = 2

View File

@@ -0,0 +1,7 @@
if True:
a = 1
b = 2
def f():
<selection>c = 3</selection><caret>

View File

@@ -0,0 +1,7 @@
<selection>if True:
a = 1
b = 2
</selection>
def f():
c = 3

View File

@@ -0,0 +1,9 @@
if True:
a = 1
b = 2
def f():
if True:
a = 1
b = 2

View File

@@ -0,0 +1,7 @@
if True:
a = 1
b = 2
def f():
<selection> c = 3</selection><caret>

View File

@@ -0,0 +1,7 @@
<selection>if True:
a = 1
b = 2
</selection>
def f():
c = 3

View File

@@ -0,0 +1,8 @@
if True:
a = 1
b = 2
def f():
if True:
a = 1
b = 2

View File

@@ -0,0 +1,7 @@
if True:
a = 1
b = 2
def f():
<selection> c = 3
<caret></selection>

View File

@@ -0,0 +1,7 @@
<selection>if True:
a = 1
b = 2
</selection>
def f():
c = 3

View File

@@ -0,0 +1,10 @@
if True:
a = 1
b = 2
def f():
if True:
a = 1
b = 2

View File

@@ -0,0 +1,7 @@
if True:
a = 1
b = 2
def f():
<caret><selection>c = 3</selection>

View File

@@ -0,0 +1,7 @@
<selection>if True:
a = 1
b = 2
</selection>
def f():
c = 3

View File

@@ -0,0 +1,9 @@
if True:
a = 1
b = 2
def f():
if True:
a = 1
b = 2

View File

@@ -0,0 +1,7 @@
if True:
a = 1
b = 2
def f():
<caret><selection> c = 3</selection>

View File

@@ -0,0 +1,7 @@
<selection>if True:
a = 1
b = 2
</selection>
def f():
c = 3

View File

@@ -0,0 +1,9 @@
if True:
a = 1
b = 2
def f():
if True:
a = 1
b = 2

View File

@@ -0,0 +1,8 @@
if True:
a = 1
b = 2
def f():
<caret><selection> c = 3
</selection>

View File

@@ -0,0 +1,7 @@
<selection>if True:
a = 1
b = 2
</selection>
def f():
c = 3

View File

@@ -1,7 +1,6 @@
def foo(self): def foo(self):
x = 1 x = 1
y = 2 y = 2
def foo(self): def foo(self):
x = 1 x = 1
y = 2 y = 2

View File

@@ -1,9 +1,8 @@
def foo(self): def foo(self):
x = 1 x = 1
y = 2 y = 2
def foo(self):
def foo(self): x = 1
x = 1 y = 2
y = 2
z = 3 z = 3

View File

@@ -1,8 +1,6 @@
def f(): def f():
a = 1 a = 1
b = 2 b = 2
def f(): def f():
a = 1 a = 1
b = 2 b = 2

View File

@@ -47,6 +47,30 @@ public class PyCopyPasteTest extends PyTestCase {
doTest(); doTest();
} }
public void testSelection1() { //PY-6994
doTest();
}
public void testSelection2() { //PY-6994
doTest();
}
public void testSelection3() { //PY-6994
doTest();
}
public void testSelectionReverse1() { //PY-6994
doTest();
}
public void testSelectionReverse2() { //PY-6994
doTest();
}
public void testSelectionReverse3() { //PY-6994
doTest();
}
public void testIndent11() { public void testIndent11() {
doTestSingleLine(); doTestSingleLine();
} }