From 14d89ce4c69ccf5043c6a75b8d0773e20d9e04fb Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 2 Dec 2011 15:21:48 +0100 Subject: [PATCH] fixed PY-5202 Move statement: breaks code on moving outside with statement --- .../moveUpDown/StatementMover.java | 46 ++++++++++--------- python/testData/mover/with.py | 6 +++ python/testData/mover/with_afterDown.py | 6 +++ python/testData/mover/with_afterUp.py | 6 +++ .../python/PyStatementMoverTest.java | 10 ++++ 5 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 python/testData/mover/with.py create mode 100644 python/testData/mover/with_afterDown.py create mode 100644 python/testData/mover/with_afterUp.py diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/moveUpDown/StatementMover.java b/python/src/com/jetbrains/python/codeInsight/editorActions/moveUpDown/StatementMover.java index 4cb09768f420..c7bc7be2a576 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/moveUpDown/StatementMover.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/moveUpDown/StatementMover.java @@ -214,10 +214,9 @@ public class StatementMover extends LineMover { * @return first is the element which we move * second is the element we move to */ - private Pair getStatementParts(MoveInfo info, Editor editor, PsiFile file, boolean down) { + private Pair getStatementParts(MoveInfo info, Editor editor, PsiFile file, boolean down) { PsiElement element1 = myStatementToMove; - PyStatementPart statementPart1 = PsiTreeUtil.getParentOfType(element1, PyStatementPart.class, false); - + PyElement statementPart1 = PsiTreeUtil.getParentOfType(element1, PyStatementPart.class, PyWithStatement.class); int offset2 = getLineStartSafeOffset(editor.getDocument(), info.toMove2.startLine); PsiElement element2 = file.findElementAt(offset2-1); if (element2 instanceof PsiWhiteSpace) { @@ -242,11 +241,11 @@ public class StatementMover extends LineMover { } } } - PyStatementPart statementPart2 = PsiTreeUtil.getParentOfType(element2, PyStatementPart.class); + PyElement statementPart2 = PsiTreeUtil.getParentOfType(element2, PyStatementPart.class, PyWithStatement.class); //in case we move very last line outside if statement - if (statementPart2 != null) { - PyStatementList stList = statementPart2.getStatementList(); + if (statementPart2 instanceof PyStatementPart) { + PyStatementList stList = ((PyStatementPart)statementPart2).getStatementList(); if (stList != null && stList.getStatements().length > 0) { if (down && stList.getStatements()[stList.getStatements().length-1] == element2) { PyStatementPart parent = PsiTreeUtil.getParentOfType(statementPart2, PyStatementPart.class); @@ -262,22 +261,22 @@ public class StatementMover extends LineMover { } } - return new Pair(statementPart1, statementPart2); + return new Pair(statementPart1, statementPart2); } private boolean isMoveToCompound(MoveInfo info, Editor editor, PsiFile file, boolean down) { - Pair statementParts = getStatementParts(info, editor, file, down); - PyStatementPart statementPart1 = statementParts.first; - PyStatementPart statementPart2 = statementParts.second; - + Pair statementParts = getStatementParts(info, editor, file, down); + PyElement statementPart1 = statementParts.first; + PyElement statementPart2 = statementParts.second; if (statementPart2 != null) { - prepareToStatement(statementPart2, editor.getDocument()); + if (statementPart2 instanceof PyStatementPart) + prepareToStatement((PyStatementPart)statementPart2, editor.getDocument()); if (statementPart1 == null) return true; if (statementPart1.getParent() != statementPart2.getParent()) { PsiElement commonParent = PsiTreeUtil.findCommonParent(statementPart1, statementPart2); if (PsiTreeUtil.isAncestor(statementPart2, statementPart1, false)) return false; if ((commonParent instanceof PyIfStatement) || (commonParent instanceof PyLoopStatement) || - (commonParent instanceof PyStatementPart)) + (commonParent instanceof PyStatementPart) || (commonParent instanceof PyWithStatement)) return true; } } @@ -285,14 +284,15 @@ public class StatementMover extends LineMover { } private boolean isMoveOut(MoveInfo info, Editor editor, PsiFile file, boolean down) { - Pair insertDeleteParts = getStatementParts(info, editor, file, down); - PyStatementPart statementPart1 = insertDeleteParts.first; - PyStatementPart statementPart2 = insertDeleteParts.second; + Pair insertDeleteParts = getStatementParts(info, editor, file, down); + PyElement statementPart1 = insertDeleteParts.first; + PyElement statementPart2 = insertDeleteParts.second; if (statementPart1 != null) { if (statementPart2 == null) return true; if (statementPart1.getParent() != statementPart2.getParent()) { PsiElement commonParent = PsiTreeUtil.findCommonParent(statementPart1, statementPart2); - if (!(commonParent instanceof PyIfStatement) && !(commonParent instanceof PyLoopStatement) && !(commonParent instanceof PyStatementPart)) + if (!(commonParent instanceof PyIfStatement) && !(commonParent instanceof PyLoopStatement) && !(commonParent instanceof PyStatementPart) + && !(commonParent instanceof PyWithStatement)) return true; if (PsiTreeUtil.isAncestor(statementPart2, statementPart1, false)) return true; } @@ -312,12 +312,14 @@ public class StatementMover extends LineMover { } private boolean isTheSameIndentLevel(MoveInfo info, Editor editor, PsiFile file, boolean down) { - Pair statementParts = getStatementParts(info, editor, file, down); - myStatementPartToRemovePass = statementParts.second; - PyStatementPart statementPart1 = statementParts.first; - PyStatementPart statementPart2 = statementParts.second; + Pair statementParts = getStatementParts(info, editor, file, down); + if (statementParts.second instanceof PyStatementPart) + myStatementPartToRemovePass = (PyStatementPart)statementParts.second; + PyElement statementPart1 = statementParts.first; + PyElement statementPart2 = statementParts.second; - if (statementPart2 != null && statementPart1 != null && statementPart1.getParent() == statementPart2.getParent()) return true; + if (statementPart2 != null && statementPart1 != null && statementPart1.getParent() == statementPart2.getParent() || + statementPart2 == statementPart1) return true; return false; } diff --git a/python/testData/mover/with.py b/python/testData/mover/with.py new file mode 100644 index 000000000000..ebf76d89986b --- /dev/null +++ b/python/testData/mover/with.py @@ -0,0 +1,6 @@ +def temp(filepath): + a = 1 + with open(filepath) as f: + l = f.readlines() + for line in l: + a = 1 diff --git a/python/testData/mover/with_afterDown.py b/python/testData/mover/with_afterDown.py new file mode 100644 index 000000000000..4c0ed6aa5c8d --- /dev/null +++ b/python/testData/mover/with_afterDown.py @@ -0,0 +1,6 @@ +def temp(filepath): + a = 1 + with open(filepath) as f: + for line in l: + l = f.readlines() + a = 1 diff --git a/python/testData/mover/with_afterUp.py b/python/testData/mover/with_afterUp.py new file mode 100644 index 000000000000..18226011d47c --- /dev/null +++ b/python/testData/mover/with_afterUp.py @@ -0,0 +1,6 @@ +def temp(filepath): + a = 1 + l = f.readlines() + with open(filepath) as f: + for line in l: + a = 1 diff --git a/python/testSrc/com/jetbrains/python/PyStatementMoverTest.java b/python/testSrc/com/jetbrains/python/PyStatementMoverTest.java index dad281ab0479..1bcb2940283a 100644 --- a/python/testSrc/com/jetbrains/python/PyStatementMoverTest.java +++ b/python/testSrc/com/jetbrains/python/PyStatementMoverTest.java @@ -3,6 +3,7 @@ package com.jetbrains.python; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.LanguageLevel; /** * @author Alexey.Ivanov @@ -115,4 +116,13 @@ public class PyStatementMoverTest extends PyTestCase { public void testEmptyLine() { // PY-5197 doTest(); } + + public void testWith() { // PY-5202 + try { + setLanguageLevel(LanguageLevel.PYTHON27); + doTest(); + } finally { + setLanguageLevel(null); + } + } }