From 77a3189d40bfcac007d99ac8b9f888dbae32ad07 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 8 Dec 2009 19:25:03 +0300 Subject: [PATCH] work in progress on fixing python surround --- .../python/PythonFormattingModelBuilder.java | 10 ++--- .../PyStatementSurroundDescriptor.java | 2 +- .../statements/PyWithIfElseSurrounder.java | 9 +++- .../statements/PyWithIfSurrounder.java | 7 +++- .../statements/PyWithTryExceptSurrounder.java | 8 +++- ...r.java => PyWithTryFinallySurrounder.java} | 2 +- .../statements/PyWithWhileSurrounder.java | 10 ++++- python/testData/surround/SurroundWithIf.py | 3 ++ .../testData/surround/SurroundWithIf_after.py | 4 ++ .../surround/SurroundWithTryExcept.py | 3 ++ .../surround/SurroundWithTryExcept_after.py | 6 +++ python/testData/surround/SurroundWithWhile.py | 3 ++ .../surround/SurroundWithWhile_after.py | 4 ++ .../jetbrains/python/PySurroundWithTest.java | 42 +++++++++++++++++++ 14 files changed, 97 insertions(+), 16 deletions(-) rename python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/{PyWithTryFinnalySurrounder.java => PyWithTryFinallySurrounder.java} (96%) create mode 100644 python/testData/surround/SurroundWithIf.py create mode 100644 python/testData/surround/SurroundWithIf_after.py create mode 100644 python/testData/surround/SurroundWithTryExcept.py create mode 100644 python/testData/surround/SurroundWithTryExcept_after.py create mode 100644 python/testData/surround/SurroundWithWhile.py create mode 100644 python/testData/surround/SurroundWithWhile_after.py create mode 100644 python/testSrc/com/jetbrains/python/PySurroundWithTest.java diff --git a/python/src/com/jetbrains/python/PythonFormattingModelBuilder.java b/python/src/com/jetbrains/python/PythonFormattingModelBuilder.java index b845163b4118..b5ecc7117665 100644 --- a/python/src/com/jetbrains/python/PythonFormattingModelBuilder.java +++ b/python/src/com/jetbrains/python/PythonFormattingModelBuilder.java @@ -1,9 +1,6 @@ package com.jetbrains.python; -import com.intellij.formatting.FormattingModel; -import com.intellij.formatting.FormattingModelBuilder; -import com.intellij.formatting.FormattingModelProvider; -import com.intellij.formatting.Indent; +import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -16,7 +13,7 @@ import org.jetbrains.annotations.NotNull; * @author yole */ public class PythonFormattingModelBuilder implements FormattingModelBuilder { - private static final boolean DUMP_FORMATTING_AST = false; + private static final boolean DUMP_FORMATTING_AST = true; @NotNull public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) { @@ -27,6 +24,7 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilder { } final PyBlock block = new PyBlock((PythonLanguage)PythonFileType.INSTANCE.getLanguage(), element.getNode(), null, Indent.getNoneIndent(), null, settings); + FormattingModelDumper.dumpFormattingModel(block, 2, System.out); return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings); } @@ -34,7 +32,7 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilder { return null; } - private void printAST(ASTNode node, int indent) { + private static void printAST(ASTNode node, int indent) { while (node != null) { for (int i = 0; i < indent; i++) { System.out.print(" "); diff --git a/python/src/com/jetbrains/python/refactoring/surround/PyStatementSurroundDescriptor.java b/python/src/com/jetbrains/python/refactoring/surround/PyStatementSurroundDescriptor.java index b52593a804da..ac71a55d39b8 100644 --- a/python/src/com/jetbrains/python/refactoring/surround/PyStatementSurroundDescriptor.java +++ b/python/src/com/jetbrains/python/refactoring/surround/PyStatementSurroundDescriptor.java @@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull; public class PyStatementSurroundDescriptor implements SurroundDescriptor { private static Surrounder[] SURROUNDERS = {new PyWithIfSurrounder(), new PyWithIfElseSurrounder(), new PyWithWhileSurrounder(), new PyWithWhileElseSurrounder(), - new PyWithReturnSurrounder(), new PyWithTryExceptSurrounder(), new PyWithTryFinnalySurrounder()}; + new PyWithReturnSurrounder(), new PyWithTryExceptSurrounder(), new PyWithTryFinallySurrounder()}; @NotNull public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) { diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfElseSurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfElseSurrounder.java index 0dbd53a64d44..f7469c2dff8a 100644 --- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfElseSurrounder.java +++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfElseSurrounder.java @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.psi.PyIfStatement; +import com.jetbrains.python.psi.PyStatementList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,9 +25,13 @@ public class PyWithIfElseSurrounder extends PyStatementSurrounder { protected TextRange surroundStatement(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) throws IncorrectOperationException { PyIfStatement ifStatement = - PythonLanguage.getInstance().getElementGenerator().createFromText(project, PyIfStatement.class, "if True:\n \nelse:\n"); + PythonLanguage.getInstance().getElementGenerator().createFromText(project, PyIfStatement.class, "if True:\n pass\nelse: pass\n"); final PsiElement parent = elements[0].getParent(); - ifStatement.getIfPart().addRange(elements[0], elements[elements.length - 1]); + final PyStatementList statementList = ifStatement.getIfPart().getStatementList(); + assert statementList != null; + statementList.addRange(elements[0], elements[elements.length - 1]); + statementList.deleteChildRange(statementList.getFirstChild(), statementList.getFirstChild()); + ifStatement = (PyIfStatement) parent.addBefore(ifStatement, elements[0]); parent.deleteChildRange(elements[0], elements[elements.length - 1]); diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfSurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfSurrounder.java index b412c5bef8f4..dece54414dbf 100644 --- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfSurrounder.java +++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithIfSurrounder.java @@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.psi.PyIfStatement; +import com.jetbrains.python.psi.PyStatementList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +27,9 @@ public class PyWithIfSurrounder extends PyStatementSurrounder { PyIfStatement ifStatement = PythonLanguage.getInstance().getElementGenerator().createFromText(project, PyIfStatement.class, "if True:\n "); final PsiElement parent = elements[0].getParent(); - ifStatement.getIfPart().addRange(elements[0], elements[elements.length - 1]); + final PyStatementList statementList = ifStatement.getIfPart().getStatementList(); + assert statementList != null; + statementList.addRange(elements[0], elements[elements.length - 1]); ifStatement = (PyIfStatement) parent.addBefore(ifStatement, elements[0]); parent.deleteChildRange(elements[0], elements[elements.length - 1]); @@ -34,7 +37,7 @@ public class PyWithIfSurrounder extends PyStatementSurrounder { if (ifStatement == null) { return null; } - return ifStatement.getTextRange(); + return ifStatement.getIfPart().getCondition().getTextRange(); } public String getTemplateDescription() { diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java index e861059f19fc..217988020b02 100644 --- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java +++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryExceptSurrounder.java @@ -8,6 +8,7 @@ import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PythonLanguage; +import com.jetbrains.python.psi.PyStatementList; import com.jetbrains.python.psi.PyTryExceptStatement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,9 +25,12 @@ public class PyWithTryExceptSurrounder extends PyStatementSurrounder { protected TextRange surroundStatement(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) throws IncorrectOperationException { PyTryExceptStatement tryStatement = PythonLanguage.getInstance().getElementGenerator() - .createFromText(project, PyTryExceptStatement.class, "try:\n \nexcept Exception:\n"); + .createFromText(project, PyTryExceptStatement.class, "try:\n pass\nexcept:\n pass"); final PsiElement parent = elements[0].getParent(); - tryStatement.getTryPart().addRange(elements[0], elements[elements.length - 1]); + final PyStatementList statementList = tryStatement.getTryPart().getStatementList(); + assert statementList != null; + statementList.addRange(elements[0], elements[elements.length - 1]); + statementList.getFirstChild().delete(); tryStatement = (PyTryExceptStatement)parent.addBefore(tryStatement, elements[0]); parent.deleteChildRange(elements[0], elements[elements.length - 1]); diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinnalySurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java similarity index 96% rename from python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinnalySurrounder.java rename to python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java index 6ab8b925823f..2c78db20fc29 100644 --- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinnalySurrounder.java +++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithTryFinallySurrounder.java @@ -18,7 +18,7 @@ import org.jetbrains.annotations.Nullable; * Date: Aug 28, 2009 * Time: 6:52:06 PM */ -public class PyWithTryFinnalySurrounder extends PyStatementSurrounder { +public class PyWithTryFinallySurrounder extends PyStatementSurrounder { @Override @Nullable protected TextRange surroundStatement(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement[] elements) diff --git a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithWhileSurrounder.java b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithWhileSurrounder.java index d6472dfb5742..48aaa6d610b5 100644 --- a/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithWhileSurrounder.java +++ b/python/src/com/jetbrains/python/refactoring/surround/surrounders/statements/PyWithWhileSurrounder.java @@ -8,6 +8,8 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PythonLanguage; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyStatementList; import com.jetbrains.python.psi.PyWhileStatement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +28,9 @@ public class PyWithWhileSurrounder extends PyStatementSurrounder{ PyWhileStatement whileStatement = PythonLanguage.getInstance().getElementGenerator().createFromText(project, PyWhileStatement.class, "while True:\n "); final PsiElement parent = elements[0].getParent(); - whileStatement.addRange(elements[0], elements[elements.length - 1]); + final PyStatementList statementList = whileStatement.getWhilePart().getStatementList(); + assert statementList != null; + statementList.addRange(elements[0], elements[elements.length - 1]); whileStatement = (PyWhileStatement) parent.addBefore(whileStatement, elements[0]); parent.deleteChildRange(elements[0], elements[elements.length - 1]); @@ -34,7 +38,9 @@ public class PyWithWhileSurrounder extends PyStatementSurrounder{ if (whileStatement == null) { return null; } - return whileStatement.getTextRange(); + final PyExpression condition = whileStatement.getWhilePart().getCondition(); + assert condition != null; + return condition.getTextRange(); } public String getTemplateDescription() { diff --git a/python/testData/surround/SurroundWithIf.py b/python/testData/surround/SurroundWithIf.py new file mode 100644 index 000000000000..cb27a25ed131 --- /dev/null +++ b/python/testData/surround/SurroundWithIf.py @@ -0,0 +1,3 @@ +def foo(): + print "hello" + \ No newline at end of file diff --git a/python/testData/surround/SurroundWithIf_after.py b/python/testData/surround/SurroundWithIf_after.py new file mode 100644 index 000000000000..82ed0462b0c4 --- /dev/null +++ b/python/testData/surround/SurroundWithIf_after.py @@ -0,0 +1,4 @@ +def foo(): + if True: + print "hello" + \ No newline at end of file diff --git a/python/testData/surround/SurroundWithTryExcept.py b/python/testData/surround/SurroundWithTryExcept.py new file mode 100644 index 000000000000..cb27a25ed131 --- /dev/null +++ b/python/testData/surround/SurroundWithTryExcept.py @@ -0,0 +1,3 @@ +def foo(): + print "hello" + \ No newline at end of file diff --git a/python/testData/surround/SurroundWithTryExcept_after.py b/python/testData/surround/SurroundWithTryExcept_after.py new file mode 100644 index 000000000000..3b8cbfbabf1a --- /dev/null +++ b/python/testData/surround/SurroundWithTryExcept_after.py @@ -0,0 +1,6 @@ +def foo(): + try: + print "hello" + except: + pass + \ No newline at end of file diff --git a/python/testData/surround/SurroundWithWhile.py b/python/testData/surround/SurroundWithWhile.py new file mode 100644 index 000000000000..cb27a25ed131 --- /dev/null +++ b/python/testData/surround/SurroundWithWhile.py @@ -0,0 +1,3 @@ +def foo(): + print "hello" + \ No newline at end of file diff --git a/python/testData/surround/SurroundWithWhile_after.py b/python/testData/surround/SurroundWithWhile_after.py new file mode 100644 index 000000000000..43e325829700 --- /dev/null +++ b/python/testData/surround/SurroundWithWhile_after.py @@ -0,0 +1,4 @@ +def foo(): + while True: + print "hello" + \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PySurroundWithTest.java b/python/testSrc/com/jetbrains/python/PySurroundWithTest.java new file mode 100644 index 000000000000..e4dc14ba8c09 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/PySurroundWithTest.java @@ -0,0 +1,42 @@ +package com.jetbrains.python; + +import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler; +import com.intellij.lang.surroundWith.Surrounder; +import com.intellij.openapi.command.WriteCommandAction; +import com.jetbrains.python.fixtures.PyLightFixtureTestCase; +import com.jetbrains.python.refactoring.surround.surrounders.statements.PyWithIfSurrounder; +import com.jetbrains.python.refactoring.surround.surrounders.statements.PyWithTryExceptSurrounder; +import com.jetbrains.python.refactoring.surround.surrounders.statements.PyWithWhileSurrounder; + +/** + * @author yole + */ +public class PySurroundWithTest extends PyLightFixtureTestCase { + public void testSurroundWithIf() throws Exception { + doTest(new PyWithIfSurrounder()); + } + + public void testSurroundWithWhile() throws Exception { + doTest(new PyWithWhileSurrounder()); + } + + public void testSurroundWithTryExcept() throws Exception { + doTest(new PyWithTryExceptSurrounder()); + } + + private void doTest(final Surrounder surrounder) throws Exception { + String baseName = "/" + getTestName(false); + myFixture.configureByFile(baseName + ".py"); + new WriteCommandAction.Simple(myFixture.getProject()) { + @Override + protected void run() throws Throwable { + SurroundWithHandler.invoke(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile(), surrounder); + } + }.execute(); + myFixture.checkResultByFile(baseName + "_after.py"); + } + + protected String getTestDataPath() { + return PythonTestUtil.getTestDataPath() + "/surround/"; + } +}