diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index c7881fc32334..de51c0f60606 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -115,6 +115,12 @@
ConvertFormatOperatorToMethodIntention
+
+ com.jetbrains.python.codeInsight.intentions.PyFlipComparisonIntention
+ Python
+ PyFlipComparisonIntention
+
+
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index 8fcfdaef7065..e7669faadfef 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -98,6 +98,10 @@ INTN.replace.plus.with.format.operator=Replace + with string formatting operator
INTN.format.operator.to.method=Convert format operator usage to str.format method call
INTN.replace.with.method=Replace with str.format method call
+INTN.flip.comparison=Flip comparison
+INTN.flip.$0=Flip ''{0}''
+INTN.flip.$0.to.$1=Flip ''{0}'' to ''{1}''
+
# Conflict checker
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
CONFLICT.name.$0.obscured.cannot.convert=Name ''{0}'' obscured. Cannot convert.
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyFlipComparisonIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyFlipComparisonIntention.java
new file mode 100644
index 000000000000..91b9fca4db74
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyFlipComparisonIntention.java
@@ -0,0 +1,80 @@
+package com.jetbrains.python.codeInsight.intentions;
+
+import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.HashMap;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.PyTokenTypes;
+import com.jetbrains.python.PythonLanguage;
+import com.jetbrains.python.psi.PyBinaryExpression;
+import com.jetbrains.python.psi.PyElementGenerator;
+import com.jetbrains.python.psi.PyElementType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+/**
+ * Created by IntelliJ IDEA.
+ * Author: Alexey.Ivanov
+ * Date: 26.03.2010
+ * Time: 22:01:27
+ */
+public class PyFlipComparisonIntention extends BaseIntentionAction {
+ private static final Map FLIPPED_OPERATORS = new HashMap(7);
+
+ static {
+ FLIPPED_OPERATORS.put(PyTokenTypes.EQEQ, "==");
+ FLIPPED_OPERATORS.put(PyTokenTypes.NE, "!=");
+ FLIPPED_OPERATORS.put(PyTokenTypes.NE_OLD, "<>");
+ FLIPPED_OPERATORS.put(PyTokenTypes.GE, "<=");
+ FLIPPED_OPERATORS.put(PyTokenTypes.LE, ">=");
+ FLIPPED_OPERATORS.put(PyTokenTypes.GT, "<");
+ FLIPPED_OPERATORS.put(PyTokenTypes.LT, ">");
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INTN.flip.comparison");
+ }
+
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PyBinaryExpression.class, false);
+ while (binaryExpression != null) {
+ PyElementType operator = binaryExpression.getOperator();
+ if (FLIPPED_OPERATORS.containsKey(operator)) {
+ String operatorText = binaryExpression.getPsiOperator().getText();
+ String flippedOperatorText = FLIPPED_OPERATORS.get(operator);
+ if (flippedOperatorText.equals(operatorText)) {
+ setText(PyBundle.message("INTN.flip.$0", operatorText));
+ }
+ else {
+ setText(PyBundle.message("INTN.flip.$0.to.$1", operatorText, flippedOperatorText));
+ }
+ return true;
+ }
+ binaryExpression = PsiTreeUtil.getParentOfType(binaryExpression, PyBinaryExpression.class);
+ }
+ return false;
+ }
+
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ PyBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PyBinaryExpression.class, false);
+ while (binaryExpression != null) {
+ if (FLIPPED_OPERATORS.containsKey(binaryExpression.getOperator())) {
+ PyElementGenerator elementGenerator = PythonLanguage.getInstance().getElementGenerator();
+ binaryExpression.replace(elementGenerator.createBinaryExpression(project, FLIPPED_OPERATORS.get(binaryExpression.getOperator()),
+ binaryExpression.getRightExpression(),
+ binaryExpression.getLeftExpression()));
+ return;
+ }
+ binaryExpression = PsiTreeUtil.getParentOfType(binaryExpression, PyBinaryExpression.class);
+ }
+ }
+}
diff --git a/python/testData/intentions/afterFlipComparison.py b/python/testData/intentions/afterFlipComparison.py
new file mode 100644
index 000000000000..db88524a2d60
--- /dev/null
+++ b/python/testData/intentions/afterFlipComparison.py
@@ -0,0 +1,2 @@
+if 3 < (a + 2) and b < 4:
+ a = a and b
\ No newline at end of file
diff --git a/python/testData/intentions/beforeFlipComparison.py b/python/testData/intentions/beforeFlipComparison.py
new file mode 100644
index 000000000000..145ecd7a4c22
--- /dev/null
+++ b/python/testData/intentions/beforeFlipComparison.py
@@ -0,0 +1,2 @@
+if (a + 2) > 3 and b < 4:
+ a = a and b
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PyIntentionTest.java b/python/testSrc/com/jetbrains/python/PyIntentionTest.java
index 96acb1071fc1..3e05a100f841 100644
--- a/python/testSrc/com/jetbrains/python/PyIntentionTest.java
+++ b/python/testSrc/com/jetbrains/python/PyIntentionTest.java
@@ -101,4 +101,8 @@ public class PyIntentionTest extends PyLightFixtureTestCase {
public void testConvertFormatOperatorToMethod() throws Exception {
doTest(PyBundle.message("INTN.replace.with.method"), LanguageLevel.PYTHON30);
}
+
+ public void testFlipComparison() throws Exception {
+ doTest(PyBundle.message("INTN.flip.$0.to.$1", ">", "<"));
+ }
}