diff --git a/python/src/META-INF/python-plugin-common.xml b/python/src/META-INF/python-plugin-common.xml
index 1b02cfd7d813..7cd53851f868 100644
--- a/python/src/META-INF/python-plugin-common.xml
+++ b/python/src/META-INF/python-plugin-common.xml
@@ -148,6 +148,11 @@
Python
+
+ com.jetbrains.python.codeInsight.intentions.PyConvertLambdaToFunctionIntention
+ Python
+
+
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index f7d2a8834a2f..a4a812658721 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -130,7 +130,9 @@ INTN.convert.dict.literal.to.dict.constructor=Convert dict literal to dict const
INTN.quoted.string=Convert between single-quoted and double-quoted strings
INTN.quoted.string.single.to.double=Convert single-quoted string to double-quoted string
-INTN.quoted.string.double.to.single=Convert double-quoted string to sungle-quoted string
+INTN.quoted.string.double.to.single=Convert double-quoted string to single-quoted string
+
+INTN.convert.lambda.to.function=Convert lambda to function
# Conflict checker
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertLambdaToFunctionIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertLambdaToFunctionIntention.java
new file mode 100644
index 000000000000..ce0726cd99fd
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertLambdaToFunctionIntention.java
@@ -0,0 +1,100 @@
+package com.jetbrains.python.codeInsight.intentions;
+
+import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+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.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * User: catherine
+ * Intention to convert lambda to function
+ */
+public class PyConvertLambdaToFunctionIntention extends BaseIntentionAction {
+
+ @NotNull
+ public String getFamilyName() {
+ return PyBundle.message("INTN.convert.lambda.to.function");
+ }
+
+ @NotNull
+ public String getText() {
+ return PyBundle.message("INTN.convert.lambda.to.function");
+ }
+
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ PyLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyLambdaExpression.class);
+ if (lambdaExpression != null) {
+ if (lambdaExpression.getBody() != null)
+ return true;
+ }
+ return false;
+ }
+
+ public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
+ PyLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyLambdaExpression.class);
+ PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
+ if (lambdaExpression != null) {
+ String name;
+ PsiElement parent = lambdaExpression.getParent();
+ if (parent instanceof PyAssignmentStatement) {
+ name = ((PyAssignmentStatement)parent).getLeftHandSideExpression().getText();
+ }
+ else {
+ Application application = ApplicationManager.getApplication();
+ if (application != null && !application.isUnitTestMode()) {
+ AskNameDialog dialog = new AskNameDialog(project);
+ dialog.setTitle("Enter function name");
+ dialog.show();
+ if (!dialog.isOK()) return; // 'Cancel' button cancels everything
+ name = dialog.getAlias();
+ if (name.isEmpty()) return;
+ }
+ else
+ name = "function";
+ }
+
+ PyExpression body = lambdaExpression.getBody();
+ PyParameter[] parameters = lambdaExpression.getParameterList().getParameters();
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append("def ");
+ stringBuilder.append(name);
+ stringBuilder.append("(");
+ int size = parameters.length;
+ for (int i = 0; i != size; ++i) {
+ PyParameter parameter = parameters[i];
+ stringBuilder.append(parameter.getName());
+ if ( i != size - 1)
+ stringBuilder.append(",");
+ }
+ stringBuilder.append("):\n return ");
+ stringBuilder.append(body.getText());
+
+ PyFunction function = elementGenerator.createFromText(LanguageLevel.forElement(lambdaExpression),
+ PyFunction.class, stringBuilder.toString());
+
+ PyFunction pyFunction = PsiTreeUtil.getParentOfType(lambdaExpression, PyFunction.class);
+ if (pyFunction != null) {
+ pyFunction.getStatementList().addBefore(function, pyFunction.getStatementList().getStatements()[0]);
+ }
+ else {
+ PyStatement statement = PsiTreeUtil.getParentOfType(lambdaExpression, PyStatement.class);
+ file.addBefore(function, statement);
+ }
+ if (parent instanceof PyAssignmentStatement) {
+ parent.delete();
+ }
+ else {
+ lambdaExpression.replace(elementGenerator.createFromText(LanguageLevel.forElement(lambdaExpression), PyExpression.class,
+ name));
+ }
+ }
+ }
+}
diff --git a/python/testData/intentions/afterConvertLambdaToFunction.py b/python/testData/intentions/afterConvertLambdaToFunction.py
new file mode 100644
index 000000000000..619b1e392e9c
--- /dev/null
+++ b/python/testData/intentions/afterConvertLambdaToFunction.py
@@ -0,0 +1,6 @@
+def func(seq):
+ def function(x, y):
+ return (x + y) / y
+
+ newlist = reduce(function
+ , seq)
\ No newline at end of file
diff --git a/python/testData/intentions/beforeConvertLambdaToFunction.py b/python/testData/intentions/beforeConvertLambdaToFunction.py
new file mode 100644
index 000000000000..eaa151a875ac
--- /dev/null
+++ b/python/testData/intentions/beforeConvertLambdaToFunction.py
@@ -0,0 +1,2 @@
+def func(seq):
+ newlist = reduce(lambda x, y: (x+y)/y, seq)
\ 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 c5a4a0112bc3..5799c1ffb6f1 100644
--- a/python/testSrc/com/jetbrains/python/PyIntentionTest.java
+++ b/python/testSrc/com/jetbrains/python/PyIntentionTest.java
@@ -124,4 +124,8 @@ public class PyIntentionTest extends PyLightFixtureTestCase {
public void testQuotedString() {
doTest(PyBundle.message("INTN.quoted.string.double.to.single"));
}
+
+ public void testConvertLambdaToFunction() {
+ doTest(PyBundle.message("INTN.convert.lambda.to.function"));
+ }
}