diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index dd00b4ba8f7c..fc4fa9966eeb 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -34,6 +34,7 @@
+
diff --git a/python/src/com/jetbrains/python/editor/PyEnterAtIndentHandler.java b/python/src/com/jetbrains/python/editor/PyEnterAtIndentHandler.java
new file mode 100644
index 000000000000..22df807b1bfa
--- /dev/null
+++ b/python/src/com/jetbrains/python/editor/PyEnterAtIndentHandler.java
@@ -0,0 +1,42 @@
+package com.jetbrains.python.editor;
+
+import com.intellij.codeInsight.editorActions.BackspaceHandler;
+import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter;
+import com.intellij.injected.editor.EditorWindow;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.jetbrains.python.psi.PyFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author yole
+ */
+public class PyEnterAtIndentHandler extends EnterHandlerDelegateAdapter {
+ @Override
+ public Result preprocessEnter(@NotNull PsiFile file,
+ @NotNull Editor editor,
+ @NotNull Ref caretOffset,
+ @NotNull Ref caretAdvance,
+ @NotNull DataContext dataContext,
+ EditorActionHandler originalHandler) {
+ int offset = caretOffset.get();
+ if (editor instanceof EditorWindow) {
+ file = InjectedLanguageUtil.getTopLevelFile(file);
+ editor = InjectedLanguageUtil.getTopLevelEditor(editor);
+ offset = editor.getCaretModel().getOffset();
+ }
+ if (!(file instanceof PyFile)) {
+ return Result.Continue;
+ }
+
+ // honor dedent (PY-3009)
+ if (BackspaceHandler.isWhitespaceBeforeCaret(editor)) {
+ return Result.DefaultSkipIndent;
+ }
+ return Result.Continue;
+ }
+}
diff --git a/python/src/com/jetbrains/python/editor/PythonEnterHandler.java b/python/src/com/jetbrains/python/editor/PythonEnterHandler.java
index 6f3a856a881a..424218071db3 100644
--- a/python/src/com/jetbrains/python/editor/PythonEnterHandler.java
+++ b/python/src/com/jetbrains/python/editor/PythonEnterHandler.java
@@ -65,7 +65,7 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
if (isSplitLine != null) {
return Result.Continue;
}
- Document doc = editor.getDocument();
+ final Document doc = editor.getDocument();
PsiDocumentManager.getInstance(file.getProject()).commitDocument(doc);
final PsiElement element = file.findElementAt(offset);
CodeInsightSettings codeInsightSettings = CodeInsightSettings.getInstance();
@@ -145,6 +145,14 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter {
if (!PyCodeInsightSettings.getInstance().INSERT_BACKSLASH_ON_WRAP) {
return Result.Continue;
}
+ return checkInsertBackslash(file, caretOffset, dataContext, offset, doc);
+ }
+
+ private static Result checkInsertBackslash(PsiFile file,
+ Ref caretOffset,
+ DataContext dataContext,
+ int offset,
+ Document doc) {
if (offset > 0) {
final PsiElement beforeCaret = file.findElementAt(offset - 1);
if (beforeCaret instanceof PsiWhiteSpace && beforeCaret.getText().indexOf('\\') >= 0) {
diff --git a/python/testSrc/com/jetbrains/python/PyIndentTest.java b/python/testSrc/com/jetbrains/python/PyIndentTest.java
index c4149825d674..25d343bc5b8d 100644
--- a/python/testSrc/com/jetbrains/python/PyIndentTest.java
+++ b/python/testSrc/com/jetbrains/python/PyIndentTest.java
@@ -303,6 +303,16 @@ public class PyIndentTest extends PyTestCase {
" )");
}
+ public void testRespectDedent() { // PY-3009
+ doTest("if True:\n" +
+ " bar\n" +
+ "",
+ "if True:\n" +
+ " bar\n" +
+ "\n" +
+ "");
+ }
+
/*
TODO: formatter core problem?
public void testAlignListBeforeEquals() throws Exception {